场景:在进行ios环境下的web开发时,滑动可能会触发橡皮筋效果,禁用此效果有如下方案:
方案一:JS
<script>
document.body.addEventListener('touchmove', function (e) {
e.preventDefault();
}, {
passive: false
});
</script>
原理如上,即禁止浏览器的默认行为,在vue中还可以注册自定义指令:
export const stopScrollPenetrate = {
install(Vue) {
Vue.directive('stopScrollPenetrate', {
inserted(el, { value }) {
if (getOsType() !== 1) return //不是ios不需要
let startX = null
let startY = null
// 标识触点
el.addEventListener('touchstart', (e) => {
startY = e.touches[0].pageY
startX = e.touches[0].pageX
})
// 如果需要禁用el以外的局域
if (value) {
document.querySelector(value).addEventListener(
'touchmove',
(e) => {
e.preventDefault()
},
{ passive: false }
)
}
// 判断是否阻止滑动
el.addEventListener(
'touchmove',
(e) => {
const { pageY, pageX } = e.touches[0] // 手指位置的坐标
const x = Math.abs(pageX - startX)
const y = Math.abs(pageY - startY)
if (y < x) {
return
} //左右滑动不做操作
const { scrollTop, clientHeight, scrollHeight } = el
if (scrollTop + clientHeight === scrollHeight) {
if (pageY < startY) {
// 上划
e.preventDefault()
} else {
e.stopPropagation()
}
}
if (scrollTop == 0) {
if (pageY > startY) {
// 下划
e.preventDefault()
} else {
e.stopPropagation()
}
}
if (scrollTop > 0 && scrollTop < scrollHeight - clientHeight) {
e.stopPropagation()
}
},
{ passive: false }
)
},
unbind(el, { value }) {
if (value) {
document.querySelector(value)?.removeEventListener('touchmove')
}
},
})
},
}
方案二:CSS
body, .scroll-container {
overscroll-behavior: none;
}
该属性让你可以控制浏览器过度滚动时的表现 —— 也就是滚动到边界。具体效果参考张鑫旭的文章
现象:在浏览器中有效,在webview中无效。怀疑是兼容性问题,overscroll-behavior属性在低版本浏览器中不兼容,而此webview也获取不到版本信息,或许webview就没有对overscroll-behavior支持。
html, body {
overflow: hidden;
}
现象:在webview和浏览器中都可以,橡皮筋效果没有了,元素的滑动效果也没受到影响。
经过测试,方案4在iPhone12和iPhone14机子上是有效的,在iPhone13上面是无效的,追加方案
html, body {
overscroll-behavior: none;
}
总结: 保险起见,还是需要把webview的bounces设置为false,从根上阻止IOS默认效果。