小程序齐层看板 scroll-view 解决抖动

这个图分解成4块 上左:楼层 上右:基础数据 下左:固定文字 下右:楼栋
楼层可上下滑动
楼栋可左右滑动
基础信息可上下左右滑动
楼层scroll-view 与基础信息scroll-view 上下滑动关联
楼栋scroll-view 与基础信息scroll-view 左右滑动关联
当同时滑动 楼层与基础信息 并且滑动方向相反就会导致scroll事件的监听进入死循环导致页面抖动
为了解决这个问题就设想同时只能滑动一个scroll-view
就写了三个遮罩层在三个scroll-view上
当 一个scroll-view 触发了 touchstart 事件其他两个scroll-view 上面的遮罩层显示
当 scroll-view 触发了 touchend 事件三个scroll-view 上面的遮罩层隐藏
这样就解决了同时触发两个@scroll事件进入死循环
<template>
<view :style="'height:' + scrollViewHeight + ';'" id="scroll-v3" class="projectProgress">
<view v-if="isFloorMask" class="floor-mask"></view>
<view v-if="isTableMask" :style="'height:' + tableHeight + ';'" class="table-mask"></view>
<view v-if="isBuildingMask" class="building-mask"></view>
<!-- 楼层和项目构件进度汇总 -->
<view class="floorsTable">
<scroll-view @touchend="hideMask" @touchstart="floorTouchstart" @scroll="floorScrollHandler" scroll-y="true"
:scroll-top="floorScrollTop" :scroll-anchoring="true" style="height: 100%; width: 174rpx">
<view class="floors">
<view class="floorItem" v-for="floor in floorsList" :key="floor">{{ floor }}层</view>
</view>
</scroll-view>
<scroll-view @touchend="hideMask" @touchstart="tableTouchstart" @scroll="tableScrollHandler" scroll-x="true" scroll-y="true"
:scroll-top="tableScrollTop" :scroll-left="tableScrollLeft" :scroll-anchoring="true"
style="height: 100%; width: calc(100vw - 174rpx)">
<view class="allComponents">
<view class="componentTable">
<componentTable v-for="(buildingItem, index) in boardsInfo" :key="index"
:boardsInfo="buildingItem" :floorsList="floorsList">
</componentTable>
</view>
</view>
</scroll-view>
</view>
<!-- 楼栋和构件类型 -->
<view class="projectInfo">
<view class="title"> 项目详情 </view>
<scroll-view @touchend="hideMask" @touchstart="buildTouchstart" @scroll="buildingScrollHandler" scroll-x="true"
:scroll-left="buildingScrollLeft" :scroll-anchoring="true"
style="width: calc(100vw - 170rpx); height: 196rpx">
<view class="buildingAndType">
<BuildingAndType v-for="(buildingItem, index) in boardsInfo" :key="index"
:building="buildingItem.buildingName" :typeList="buildingItem.typeList">
</BuildingAndType>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
import debounce from "@/utils/deBounce.js";
import BuildingAndType from "./BuildingAndType.vue";
import componentTable from "./componentTable.vue";
import {
getBillBoardsList
} from "@/api/project.js";
export default {
name: "ProjectProgress",
components: {
BuildingAndType,
componentTable,
},
props: {
projectId: {
type: Number,
},
},
created() {
this.getBillBoardsList();
},
data() {
return {
tableHeight:'calc(100vh -20px - 44px - 44px - 196rpx)',
isFloorMask: false,
isBuildingMask: false,
isTableMask: false,
scrollViewHeight: "80vh",
floorScrollTop: 0,
tableScrollTop: 0,
tableScrollLeft: 0,
buildingScrollLeft: 0,
floorScrollFunc: false,
tableScrollFunc: false,
buildingScrollFunc: false,
floorTimer: null,
tableTimer: null,
buildingTimer: null,
boardsInfo: [],
floorsList: [],
};
},
mounted() {
uni.getSystemInfo({
success: (resu) => {
this.tableHeight = `calc(100vh - ${resu.statusBarHeight}px - 44px - 44px - 196rpx)`
const query = uni.createSelectorQuery();
query.select("#scroll-v3").boundingClientRect();
query.exec((res) => {
this.scrollViewHeight =
`calc(${resu.windowHeight}px - ${resu.statusBarHeight}px - 44px - 44px)`;
});
},
fail: (res) => {},
});
},
methods: {
hideMask() {
this.isFloorMask = false
this.isBuildingMask = false
this.isTableMask = false
},
initScrollTop(){
this.boardsInfo=[]
this.floorsList=[]
this.floorScrollTop=0
this.tableScrollTop=0
this.tableScrollLeft=0
},
// 获取项目下看板的信息
getBillBoardsList() {
this.initScrollTop()
uni.showLoading({
title:"加载中"
})
getBillBoardsList(this.projectId).then((responseData) => {
this.boardsInfo = responseData?.data?.data?.buildingUnitVOList;
uni.hideLoading()
if (this.boardsInfo) {
this.floorsListHandler();
}
}).catch(()=>{
uni.hideLoading()
})
},
// 楼层数据汇总处理
floorsListHandler() {
this.floorsList = [];
const floorsList = [];
this.boardsInfo.forEach((boardInfo) => {
Object.keys(boardInfo.floorMap).forEach((floor) => {
if (floorsList.indexOf(floor) === -1) {
floorsList.push(floor);
}
});
});
setTimeout(() => {
this.floorScrollTop = 68 * this.floorsList.length + Math.random();
this.tableScrollTop = this.floorScrollTop;
}, 100);
this.floorsList = floorsList;
},
floorTouchstart() {
this.floorScrollFunc = true;
this.isBuildingMask = true
this.isTableMask = true
},
tableTouchstart() {
this.tableScrollFunc = true;
this.isFloorMask = true
this.isBuildingMask = true
},
buildTouchstart() {
this.buildingScrollFunc = true;
this.isFloorMask = true
this.isTableMask = true
},
floorScrollHandler(e) {
if (this.floorTimer) clearTimeout(this.floorTimer);
if (!this.floorScrollFunc) return;
this.floorTimer = setTimeout(() => {
this.floorScrollFunc = false;
}, 200);
const {
scrollTop
} = e.detail;
this.tableScrollTop = scrollTop;
},
tableScrollHandler(e) {
if (this.tableTimer) clearTimeout(this.tableTimer);
if (!this.tableScrollFunc) return;
this.tableTimer = setTimeout(() => {
this.tableScrollFunc = false;
}, 200);
const {
scrollTop,
scrollLeft
} = e.detail;
this.floorScrollTop = scrollTop;
this.buildingScrollLeft = scrollLeft;
},
buildingScrollHandler(e) {
if (this.buildingTimer) clearTimeout(this.buildingTimer);
if (!this.buildingScrollFunc) return;
this.buildingTimer = setTimeout(() => {
this.buildingScrollFunc = false;
}, 200);
const {
scrollLeft
} = e.detail;
this.tableScrollLeft = scrollLeft;
},
},
};
</script>
<style lang="scss" scoped>
.projectProgress {
height: 100%;
width: 100vw;
background-color: #ffffff;
border-top: 2rpx solid #dfdfdf;
box-sizing: border-box;
.floorsTable {
height: calc(100% - 196rpx);
background-color: #ffffff;
display: flex;
box-sizing: border-box;
.floors {
width: 174rpx;
min-height: 100%;
color: #333333;
font-size: 28rpx;
display: flex;
flex-direction: column-reverse;
.floorItem {
box-sizing: border-box;
height: 68rpx;
width: 100%;
text-align: center;
border-top: 2rpx solid #dfdfdf;
border-right: 2rpx solid #dfdfdf;
border-left: 2rpx solid #dfdfdf;
padding-top: 10rpx;
}
}
.allComponents {
display: flex;
flex-direction: row;
min-width: calc(100vw - 174rpx);
min-height: 100%;
flex-direction: column-reverse;
.componentTable {
display: flex;
}
}
}
.projectInfo {
height: 196rpx;
border: 2rpx solid #dfdfdf;
display: flex;
box-sizing: border-box;
.title {
height: 196rpx;
line-height: 170rpx;
background-color: #f8f8f8;
color: #333333;
font-size: 28rpx;
writing-mode: vertical-lr;
text-align: center;
z-index: 97;
letter-spacing: 8rpx;
border-right: 2rpx solid #dfdfdf;
box-sizing: border-box;
}
.buildingAndType {
display: flex;
}
}
}
.floor-mask {
position: fixed;
width: 174rpx;
height: 100vh;
left: 0;
bottom: 0;
top: 220rpx;
background-color: transparent;
z-index: 999999;
}
.building-mask {
position: fixed;
width: 100vw;
height: 196rpx;
left: 0;
right: 0;
bottom: 0;
background-color: transparent;
z-index: 999999;
}
.table-mask {
position: fixed;
width: calc(100vw-174rpx);
height: calc(100vh-206px);
left: 174rpx;
right: 0;
bottom: 196rpx;
background-color:transparent;
z-index: 999999;
}
</style>

浙公网安备 33010602011771号