禁止 IOS 橡皮筋效果
方法一:
首先,在拖动 div 时,判断当前容器 div 是否有滚动条,如果没有,则禁止整个 div 拖动,例:
const list_dom: any = document.querySelector(".list");
list_dom.addEventListener("touchmove",(ev) => {
if (list_dom.scrollHeight <= list_dom.clientHeight &&list_dom.offsetHeight <= list_dom.clientHeight) {
ev.preventDefault();
}
},{ passive: false });
注:上述方法仅适用于 div 内没有其他内容滚动情形!如果内层有其他 div 滚动,则需要监听当前滑动区域是否在内层滚动 div 上,如果在对应滚动 div 上,则不调用 ev.preventDefault() 方法,否则则调用。
在配置上述方法同时,对相应存在滚动的 div 设置 css 属性:
overscroll-behavior: none;
使临近滚动区域不受到滚动链影响,滚动到边界后不会带动外层滚动。
方法二:
export const getClientHeight = () => {
return (
window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight
);
};
/*
* @Function 处理touchmove, 将滚动条拖到边缘的时候,禁止橡皮筋效果
*/
class HandleTouchMove {
startX;
startY;
constructor() {
this.startX = 0;
this.startY = 0;
this.listenTouchstart = this.listenTouchstart.bind(this);
this.listenTouchmove = this.listenTouchmove.bind(this);
}
listenTouchstart = (ev: any) => {
this.startX = ev.changedTouches[0].pageX;
this.startY = ev.changedTouches[0].pageY;
};
listenTouchmove = (ev: any, _dom: any) => {
const dom = document.querySelector(_dom);
const moveEndX = ev.changedTouches[0].pageX;
const moveEndY = ev.changedTouches[0].pageY;
const moveX = moveEndX - this.startX;
const moveY = moveEndY - this.startY;
if (Math.abs(moveX) > Math.abs(moveY) && moveX > 0) {
// 向右拖拽
if (dom?.scrollLeft === 0) {
ev.cancelable && ev.preventDefault();
}
}
if (Math.abs(moveX) > Math.abs(moveY) && moveX < 0) {
// 向左拖拽
if (
dom?.scrollLeft + dom?.offsetWidth === dom?.scrollWidth &&
dom?.scrollLeft + dom?.clientWidth === dom?.scrollWidth
) {
ev.cancelable && ev.preventDefault();
}
}
if (Math.abs(moveY) > Math.abs(moveX) && moveY > 0) {
// 向下拖拽
if (dom?.scrollTop === 0) {
ev.cancelable && ev.preventDefault();
}
}
if (Math.abs(moveY) > Math.abs(moveX) && moveY < 0) {
// 向上拖拽
if (
dom?.scrollHeight - (dom?.scrollTop + dom?.offsetHeight) <= 1 &&
dom?.scrollHeight - (dom?.scrollTop + dom?.clientHeight) <= 1
) {
ev.cancelable && ev.preventDefault();
ev.stopPropagation();
}
}
};
}
export const handleTouchmove = new HandleTouchMove();
调用示例:
<template>
<div class="wrap" :style="{ height: client_height }">
<div
class="content"
@touchstart="handleTouchmove.listenTouchstart"
@touchmove="
(ev) => handleTouchmove.listenTouchmove(ev, 'content')
">
<div style="height: 1000px">132</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { getClientHeight, handleTouchmove } from "@/components/Common/utils";
import { onMounted, ref } from "vue";
const client_height: any = ref("100vh");
onMounted(() => {
client_height.value = getClientHeight() + "px";
});
</script>
<style lang="scss" scoped>
.wrap {
width: 100%;
.content {
height: 100%;
overflow-y: auto;
overscroll-behavior: none;
}
}
@supports (padding-bottom: env(safe-area-inset-bottom)) or
(padding-bottom: constant(safe-area-inset-bottom)) {
.content {
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
}
}
@supports not (padding-bottom: env(safe-area-inset-bottom)) {
.content {
padding-bottom: 20px;
}
}
@supports not (padding-bottom: constant(safe-area-inset-bottom)) {
.content {
padding-bottom: 20px;
}
}
</style>

浙公网安备 33010602011771号