移动端ios阻止橡皮筋效果

问题由来

  • 在移动端开发中,像 ios 的微信浏览器、Safari 浏览器等,在网页进行滑动的时候会出现橡皮筋效果

  • 橡皮筋效果: 当页面拉到尽头时还能继续拉动,露出浏览器的底色,松手会回弹回去

  • 这样的效果一般只会出现在 ios 中,安卓倒没有这个问题

解决办法

  • 首先想到的是 event.preventDefault() 阻止滑动的默认行为,但如果直接添加到页面上,整个页面就不会滚动了
  • 那么只有达到临界值时,再阻止事件默认行为即可,于是只需判断页面是否滚动到了顶端和底部

原生写法:

javascript 复制代码
 (function () {
   if (terminal() !== "ios") return;
   let startY, endY;
   window.addEventListener("touchstart", function (e) {
     startY = e.touches[0].pageY;
   }, { passive: false })
 ​
   window.addEventListener("touchmove", function (e) {
     endY = e.touches[0].pageY; // 记录手指触摸的移动中的坐标
     // 判断是否为向上滑行为,并且页面已经到达顶端
     const isCanUpslide = endY > startY && this.scrollY <= 0; 
     // 判断是否为向下滑行为,并且页面已经到达底部
     const isCanDownslide =
       endY < startY && this.scrollY + this.innerHeight >= document.body.scrollHeight;
     // 手指滑动页面,到达两端都不能继续滑动
     if ((isCanDownslide || isCanUpslide) && e.cancelable) e.preventDefault();
   }, { passive: false });
 })();

Jquery 写法:

javascript 复制代码
 // 使用 $.event.special 对象创建一个带有 passive 选项的自定义事件
 $.event.special.touchmove = {
   setup(_, ns, handle) {
     this.addEventListener('touchmove', handle, { passive: false });
   }
 };
 ​
 (function () {
   if (terminal() !== "ios") return;
   let startY, endY;
   $(window)
     .on("touchstart", function (e) {
       startY = e.originalEvent.touches[0].pageY;
     })
     .on("touchmove", function (e) {
       // e.preventDefault && e.preventDefault()
       endY = e.originalEvent.touches[0].pageY; // 记录手指触摸的移动中的坐标
       // 判断是否为向上滑行为,并且页面已经到达顶端
       const isCanUpslide = endY > startY && $(this).scrollTop() <= 0;
       // 判断是否为向下滑行为,并且页面已经到达底部
       const isCanDownslide =
       endY < startY && $(this).scrollTop() + $(this).height() >= $('body')[0].scrollHeight;
       if ((isCanDownslide || isCanUpslide) && e.cancelable) e.preventDefault();
     });
 })();

为什么需要判断上下滑动行为?

  • 当到达页面底部或顶部时,如果不判断滑动方向,此时无论做什么方向的滑动都会被阻止默认行为,这就造成页面不能滑动
  • 也就是说不判断上下滑动方向,和直接阻止默认行为没有什么区别

注意:需要找准自己的滚动对象,不一定是 windowbody

判断设备方法

  • 通过 navigator.userAgen 可以判断当前是不是 ios
javascript 复制代码
 function terminal() {
   var u = navigator.userAgent;
   let osType;
   if ((u && u.indexOf("Android") > -1) || u.indexOf("Linux") > -1) {
     osType = "Android";
   }
   if (u && !!u.match(/(i[^;]+;( U;)? CPU.+Mac OS X/)) {
     osType = "ios";
   }
   return osType;
 }
相关推荐
iccb101317 分钟前
我是如何实现在线客服系统的极致稳定性与安全性的
前端·javascript·后端
Keya19 分钟前
解决 pod install 警告信息显示不完全的方法
ios·xcode·cocoapods
宇宙全栈Link22 分钟前
当 React 组件调用自定义 hooks,hooks 又调用其他 hooks 时,状态变化如何传播?
前端·javascript·react.js
南方kenny23 分钟前
从0到1理解JS事件委托:让你的代码性能提升一个level
前端·javascript
西瓜树枝23 分钟前
用 iframe 实现前端批量下载的优雅方案 —— 从原理到实战
前端·javascript
归于尽24 分钟前
原生JS与React的事件差异
前端·javascript·react.js
独立开阀者_FwtCoder1 小时前
面试官:为什么在 Vue3 中 ref 变量要用 .value?
前端·javascript·vue.js
独立开阀者_FwtCoder1 小时前
手握两大前端框架,Vercel 再出手拿下 Nuxt.js,对前端有什么影响?
前端·javascript·vue.js
独立开阀者_FwtCoder1 小时前
弃用 html2canvas!快 93 倍的截图神器!
前端·javascript·vue.js
伍哥的传说1 小时前
H3初识——入门介绍之常用中间件
前端·javascript·react.js·中间件·前端框架·node.js·ecmascript