第一章 uniapp实现兼容多端的树状族谱关系图,创建可缩放移动区域
完成效果“
uniapp树状族谱关系图
本章效果:
1.设置可移动缩放区域
template:
<view class="tree cx-fex cx-fex-itemsc cx-fex-c">
<movable-area class="movable-area" v-show="treeData.length":style="{'paddingBottom': `calc(${systemInfo.safeAreaInsetBottom}px + 136rpx)`, 'box-sizing': 'border-box', 'width': `${windowSizeComputed.width}`, 'height': `calc(${windowSizeComputed.height}px - ${systemInfo.safeAreaInsetBottom}px - 136rpx)`}"><movable-view :x="left" :y="top" direction="all" scale :scale-value="scaleNum" scale-min="0.01"class="movable-view" :out-of-bounds="false" :style="{ 'width': `fit-content`, 'height': `fit-content` }"@scale="movableViewScale" @change="movableViewScale"><view class="content"><tree-item ref="treeItem" :tree-data="treeData" :tree-first="true" :pageType="pageType" init /></view></movable-view></movable-area><view class="addBtn" v-show="!treeData.length" @click="addAncestors">+ 点击马上添加族人</view>
<bottom-button @touch="pageSubmit">{{ pageType == 'preview' ? '下载族谱' : '发布' }}</bottom-button></view>
script:
computed:{...mapState(['systemInfo']),//屏幕宽高windowSizeComputed: {get() {let {width,height} = this.x_ylet {systemInfo} = thisreturn {width: width || '100%',height: height || systemInfo.windowHeight}},set(width, height) {this.x_y = {width,height}}},
},
data:{//族谱数据treeData: [// {// name: "章龙操",// sex: 1,// address: "江西省抚州市",// desc: 1,// type: ['刘配氏', '章配氏'],// child: [],// checked: true,// addressCopy: ['江西省', '抚州市', '临川区']// },],
}
css:
@mixin formStyle {.form {height: calc(100% - 200rpx);// 家庭成员类型.family-item {width: 231rpx;height: 71rpx;line-height: 71rpx;text-align: center;background: #FFFFFF;border-radius: 10rpx;border: 1px solid #B98C52;margin-bottom: 20rpx;&.lastChild {width: 100%;}}.for-item {height: 25%;margin-bottom: 20rpx;.label {width: 120rpx;.required {color: red;}}.input {width: calc(100% - 120rpx);height: 70rpx;line-height: 70rpx;&.textarea {height: auto;}&.text {padding: 0 5px;box-sizing: border-box;border: 1px solid rgba(231, 231, 231, 1);border-radius: 10rpx;font-size: 12px;}.man {margin-right: 90rpx;}.icon {width: 24rpx;height: 24rpx;border-radius: 50%;border: 1px solid rgba(231, 231, 231, 1);position: relative;margin-right: 13rpx;}.icon.active {width: 24rpx;height: 24rpx;border-radius: 50%;border: 1px solid #B98C52;position: relative;margin-right: 13rpx;.iconContent {width: 14rpx;height: 14rpx;border-radius: 50%;background: #B98C52;}}.ReleaseAreaText {width: 100%;height: 240rpx !important;max-height: 240rpx;border: 1px solid rgba(231, 231, 231, 1);border-radius: 10rpx;padding: 5px;box-sizing: border-box;}&.desc {& /deep/ .uni-select {padding: 0 5px;box-sizing: border-box;}}&.spouse {display: grid;grid-template-columns: repeat(3, 1fr);gap: 2.5%;.item {width: 100%;padding: 12rpx 0;line-height: 1;border-radius: 10rpx;margin: 8rpx 0;text-align: center;position: relative;&.active {background: rgba(179, 136, 80, .1);color: #895C22;}&.off {background-color: #f8f8f8;}.zlc-bianji {position: absolute;top: -6rpx;right: -6rpx;font-size: 28rpx;}}}.timePicker {width: calc(100% - 30rpx);}}}}}@mixin headerStyle {.header {width: 100%;height: 100rpx;line-height: 100rpx;.title {font-weight: 700;}.icon {font-size: 40rpx;}}}@mixin footerStyle {.footer {height: 100rpx;line-height: 100rpx;.btn {width: 280rpx;height: 80rpx;text-align: center;line-height: 80rpx;background: #B98D55;border-radius: 40rpx;color: #fff;}}}.tree {width: 100%;height: 100%;background-color: #f8f8f8;background-size: 0.5cm 0.5cm;background-image:linear-gradient(to right, rgba(231, 231, 231, 1) 1px, transparent 1px),linear-gradient(to bottom, rgba(231, 231, 231, 1) 1px, transparent 1px);// padding-bottom: calc(env(safe-area-inset-bottom) + 116rpx);// padding-bottom: calc(constant(safe-area-inset-bottom) + 116rpx);box-sizing: border-box;overflow: hidden;position: relative;.movable-area-add {width: 70rpx;right: 0;position: fixed;pointer-events: none;z-index: 999;.movable-view-add {width: fit-content;height: fit-content;pointer-events: auto;.addShow {width: 90rpx;height: 90rpx;line-height: 90rpx;text-align: center;background: #FFFFFF;box-shadow: 0rpx 2rpx 13rpx 0rpx rgba(0, 0, 0, 0.05);border-radius: 50%;font-weight: 400;font-size: 26rpx;color: #895C22;}}}.addBtn {width: 352rpx;height: 152rpx;line-height: 152rpx;text-align: center;background: #FFFFFF;box-shadow: 0rpx 2rpx 13rpx 0rpx rgba(0, 0, 0, 0.05);border-radius: 10rpx;border: 2px solid #B98C52;}.main {width: 570rpx;height: fit-content;background: #FFFFFF;border-radius: 20rpx;padding: 0 34rpx 40rpx;box-sizing: border-box;&.deletePersonalPopup_main {height: 350rpx;}&.loadPicture_main {width: 570rpx;height: 1000rpx;image {width: 100%;height: 100%;}}&.datePicker{width: 100%;height: 500rpx;.header{width: 100%;height: 100rpx;line-height: 100rpx;display: flex;flex-direction: row;align-items: center;justify-content: space-between;.cancel{color: #895C22;}.confirm{color: #895C22;}.tabs{width: 300rpx;height: 50rpx;display: flex;flex-direction: row;align-items: center;.pre{width: 50%;border-radius: 20rpx 0 0 20rpx;text-align: center;line-height: 50rpx;border-top: 1px solid #895C22;border-bottom: 1px solid #895C22;border-left: 1px solid #895C22;color: #895C22;&.on{color: #FFFFFF;background-color: #895C22;}}.next{width: 50%;border-radius: 0 20rpx 20rpx 0;text-align: center;line-height: 50rpx;border: 1px solid #895C22;color: #895C22;&.on{color: #FFFFFF;background-color: #895C22;}}}}.content{width: 100%;height: 400rpx;display: flex;flex-direction: row;align-items: center;justify-content: center;.BC{display: flex;flex-direction: row;align-items: center;justify-content: center;.ipt{width: 100rpx;height: 50rpx;border: 1px solid #895C22;border-radius: 10rpx;&.month{margin-left: 20rpx;}}.label{&.month{margin-right: 20rpx;}}}}}@include headerStyle();@include formStyle();@include footerStyle();&.ReleasePopup {height: fit-content;.form {.for-item {height: fit-content;margin-bottom: 20rpx;.label {width: 140rpx;}.input {width: calc(100% - 140rpx);& /deep/ input {width: 100%;text-align: left;}&.noBorder {border: none;height: fit-content;}&.birthday {.zlcIcon {font-size: 40rpx;}}& /deep/ .uni-select {padding: 0 5px;box-sizing: border-box;}}.genealogy_image {.imgBox {width: fit-content;height: fit-content;position: relative;.cx-icon {width: 30rpx;height: 30rpx;font-size: 30rpx;position: absolute;right: -9rpx;top: -30rpx;color: #B98C52;// background: #fff;border-radius: 50%;&::before {width: 100%;height: 100%;border-radius: 50%;background: #FFFFFF;top: -30rpx !important;}}.item {width: 150rpx;height: 150rpx;border-radius: 20rpx;box-shadow: 0rpx 0rpx 10rpx rgba(0, 0, 0, 0.5);}}}}}}}.content {width: fit-content;height: fit-content;}.loadGenealogy {position: absolute;left: -500%;top: -500%;width: fit-content;height: fit-content;}}
2.在app.vue获取设备信息
<script>export default {onLaunch: function() {console.log('App Launch');this.getPhoneHeight();},onShow: function() {console.log('App Show')},onHide: function() {console.log('App Hide')},methods: {getPhoneHeight() { //获取高度let that = this;let systemInfo = {};uni.getSystemInfo({success: function(res) {if (res.platform == "ios") {systemInfo.toBar = 44;} else if (res.platform == "android") {systemInfo.toBar = 48;} else {systemInfo.toBar = 44;}if (res.safeArea.top > 40) {systemInfo.isIphoneX = true;}systemInfo.windowWidth = res.screenWidth; //windowWidthsystemInfo.windowHeight = res.screenHeight; //windowHeightsystemInfo.statusBarHeight = res.statusBarHeight; //状态栏的高度systemInfo.heightBlank = Number(systemInfo.statusBarHeight) + Number(systemInfo.toBar);systemInfo.safeAreaInsetBottom = res.safeAreaInsets.bottom //ios底部安全距离that.$store.commit('SET_SYSTEMINFO', systemInfo);},});},}}
</script><style>@import url('@/static/css/iconfont.css');/*每个页面公共css */page {background-color: #f8f8f8;--default-color: #895C22;width: 100%;height: 100%;}:not(not) {box-sizing: border-box}
</style>
3.vuex仓库代码
import {stat
} from 'fs';
import Vue from 'vue';
import VueX from 'vuex';
Vue.use(VueX);const store = new VueX.Store({state: {systemInfo: null,},mutations: {SET_SYSTEMINFO(state, payload) {state.systemInfo = payload;state.systemInfo.pageMarginTop = state.systemInfo.statusBarHeight * 2 + 90;},},
})
export default store