IOS Safari浏览器橡皮筋效果的禁用

743 阅读1分钟

场景:在进行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默认效果。