这个问题好几个项目到遇到,一直没得到很好(完美)的解决,可能之前的项目比较赶,一直没时间去研究,后面到了一家相对比较自由的公司,终于有时间研究这些疑难杂症了,然后就想到了一个办法:
1.对于浮动的按钮,或者页面上可以滑动的元素,可以这么做,当touchStart事件被触发的时候,就执行以下代码:
document.body.style.overflow = 'hidden'
当touchend事件被触发的时候,就执行以下代码:
document.body.style.overflow = 'auto'
然后就发现拖动按钮或者元素底层的页面就不会滑动了
2.对于弹窗,原理也相同,出现弹窗的时候执行:
document.body.style.overflow = 'hidden'
关闭弹窗的时候执行:
document.body.style.overflow = 'auto'
若您还不清楚,我写个完整的vue项目demo组件,是对于以上第一点,在页面上滑动浮动按钮的,然后您在页面中直接引入这个组件即可查看到效果:
<style lang="scss">
.float_info{
box-shadow: 0px 1px 1px 1px rgba(0, 0, 0, 0.1);
color: #666666;
transition: all 0.3s;
position: fixed;
bottom: 436px;
right: 6px;
width: 80px;
height: 80px;
display: flex;
flex-flow: column;
justify-content: center;
align-items: center;
z-index: 999;
// background: rgba(0, 0, 0, 0.5);
border-radius: 35px;
cursor: pointer;
// user-select: none;
.text{
font-size: 24px;
color: #fff;
}
img{
width: 44px;
height: 44px;
}
}
</style>
<template>
<div
ref="floatButton"
class="float_info"
:style="{'width': itemWidth + 'px', 'height': itemHeight + 'px', 'left': left + 'px', 'top': top + 'px'}"
@touchstart="touchStart"
@touchmove="touchmove"
@touchend="touchend"
@click="onBtnClicked"
>
<img src="../assets/img/fifteenCul.png" :style="{'width': itemWidth + 'px', 'height': itemHeight + 'px'}">
</div>
</template>
<script>
export default {
data() {
return {
clientWidth: 0,
clientHeight: 0,
timer: null,
currentTop: 0,
left: 0,
top: 0,
floatButton:''
}
},
props: {
itemWidth: { // 悬浮按钮宽度
type: Number,
default: 70
},
itemHeight: { // 悬浮按钮高度
type: Number,
default: 70
},
gapWidth: { // 距离左右两边距离
type: Number,
default: 10
},
coefficientHeight: { // 从上到下距离比例
type: Number,
default: 0.55
}
},
created() {
this.clientWidth = document.documentElement.clientWidth
this.clientHeight = document.documentElement.clientHeight
this.left = this.clientWidth - this.itemWidth - this.gapWidth
this.top = this.clientHeight - this.itemWidth - this.gapWidth - 40
},
mounted() {
this.floatButton = this.$refs.floatButton
},
methods: {
onBtnClicked(){
console.log('onBtnClicked')
this.$emit("onFloatBtnClicked")
},
handleScrollStart() {
this.timer && clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.handleScrollEnd()
}, 300)
this.currentTop = document.documentElement.scrollTop || document.body.scrollTop
if(this.left > this.clientWidth / 2) {
this.left = this.clientWidth - this.itemWidth / 2
} else {
this.left = -this.itemWidth / 2
}
},
handleScrollEnd(){
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
if(scrollTop === this.currentTop) {
if(this.left > this.clientWidth/2) {
this.left = this.clientWidth - this.itemWidth - this.gapWidth
} else {
this.left = this.gapWidth
}
clearTimeout(this.timer)
}
},
touchStart() {
this.floatButton.style.transition = 'none'
document.body.style.overflow = 'hidden'
},
touchmove(e) {
if (e.targetTouches.length === 1) { // 一根手指
let touch = e.targetTouches[0]
this.left = touch.clientX - (this.itemWidth/2)
this.top = touch.clientY - (this.itemWidth/2)
}
},
touchend() {
document.body.style.overflow = 'auto'
this.floatButton.style.transition = 'all 0.3s'
if(this.left > document.documentElement.clientWidth / 2) {
this.left = document.documentElement.clientWidth - this.itemWidth- this.gapWidth
}else{
this.left = 0 + this.gapWidth
}
if(this.top>(document.documentElement.clientHeight-this.itemWidth)) {
this.top = document.documentElement.clientHeight-this.itemWidth- this.gapWidth
}
if(this.top<this.itemWidth) {
this.top = 0 + this.gapWidth
}
},
},
}
</script>