Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS 13.4 下 bounce 存在异常 #978

Closed
xiaojundebug opened this issue Mar 25, 2020 · 15 comments
Closed

iOS 13.4 下 bounce 存在异常 #978

xiaojundebug opened this issue Mar 25, 2020 · 15 comments

Comments

@xiaojundebug
Copy link

xiaojundebug commented Mar 25, 2020

Version

1.15.2

Reproduction link

http://ustbhuangyi.com/music/#/recommend

Steps to reproduce

快速滑动,当触发bounce时,你会看到 list 大跳一下,请参考你们官方播放器 demo (http://ustbhuangyi.com/music/#/recommend)

What is expected?

正常弹回

What is actually happening?

bounce渲染异常


我本地能复现,并不是官方 demo 个例

@xiaojundebug
Copy link
Author

今天刚升级的iOS版本就坏了,昨天还好好的

@tanlucheng
Copy link

今天刚升级的iOS版本就坏了,昨天还好好的

就是iOS 13.4 才会出现的,我现在也遇到了,项目生产环境在用着。急!请问有解决办法吗

@theniceangel
Copy link
Collaborator

@tanlucheng 是在什么浏览器下面,微信还是safari?

@theniceangel
Copy link
Collaborator

@xiaojun1994 @tanlucheng 我测试了一下,是在iOS 13.4 && wkwebview 的情况下,会出现这个情况,目前的解决方案就是根据 ua 在实例化 bs 的时候传入关闭 bounce 的配置。

{
   bounce: {
       top: false,
       bottom: false
   }
}

@theniceangel
Copy link
Collaborator

或者还有另外一种方案,默认采取 raf 作为滚动方式,这样性能可能没有用 css 方案好,配置如下:

{
    useTransition: false
}

@theniceangel
Copy link
Collaborator

目前 wkwebview 是存在许多bug,我在实际的公司业务中也是遇到很多问题

@tanlucheng
Copy link

tanlucheng commented Apr 2, 2020 via email

@jemmy-tang
Copy link

先给个大致的思路:
1.禁止回弹效果,但是不能用bounce:false的配置,否则下拉刷新和上拉加载功能没法使用
2.滚动分为手指离开屏幕的滑动和触摸中的滑动;触摸中的滑动不会出发ios13.4下的bug
3.那这里就要解决手指离开屏幕的滑动了,监听scroll事件,判断y值顶部和底部的临界值,超过后用scrollTo归位。这样就不会触发回弹效果了。

@jemmy-tang
Copy link

jemmy-tang commented Apr 15, 2020

  let isTouching = false; //是否正在触摸屏
  let scrollYBottom = 0; //滚动到底部的值
  let isPullingDown = false; //是否在下拉过程中,避免下拉后立刻回弹,保留回弹效果
  let isPullingUp = false; //是否在上拉过程中, 避免上拉后立刻回弹,保留回弹效果

  const ver = navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);
  //判断ios是否大于13.4
  const isIosVerLgThan1304 = ver && ver.length > 3 && ver[1] >= 13 && ver[2] >= 4; //判断ios是否大于13.4

  const oWrapper = document.getElementById("wrapper");

  const scroll = new BScroll("#wrapper", {});

  if (isIosVerLgThan1304) {
    scroll.on("scroll", (pos) => {
      //根据Y值判断是否下拉结束
      if (pos.y <= 0 && isPullingDown) isPullingDown = false;
      if (pos.y >= scrollYBottom && isPullingUp) isPullingUp = false;

      if (isTouching) return;

      //限制正常滑动过程中scroll顶部回弹
      if (!isPullingDown && pos.y >= 0) {
        scroll.scrollTo(0, 0, 0);
      }

      //限制正常滑动过程中scroll底部回弹
      if (!isPullingUp && scrollYBottom >= pos.y) {
        scroll.scrollYTo(0, scrollYBottom, 0);
      }
    });

    oWrapper.addEventListener("touchstart", () => {
      //每次触摸时重新计算滚动到底部Y值... 解决开启上拉加载后,内容高度会变
      scrollYBottom = scroll.wrapperHeight - scroll.scrollerHeight;
      isTouching = true;
    });
    oWrapper.addEventListener("touchend", () => {
      if (scroll.y > 0) isPullingDown = true; //保持下拉状态
      if (scroll.y < scrollYBottom) isPullingUp = true; //保持上拉状态
      isTouching = false;
    });
  }

上面是从我的react组件中剥离出来的逻辑(简化版),此段代码没测试过,大致逻辑是这样的。
注:自己封装的react组件中亲测有效,牺牲下13.4下的回弹效果

@moahmn
Copy link

moahmn commented Apr 20, 2020

同事的今天也说了这个问题,也能复现,13.4的ios

@Fogwind
Copy link

Fogwind commented May 15, 2020

根据@jemmy-tang的思路,整理的我的解决方法:

let bScrollInstance = null;
let loadFinish = false; // 数据是否全部加载完成 当你调用closePullUp()函数时把loadFinish的值修改为true。

init();

function init() {
        bScrollInstance = new BScroll('#wrapper', {
          scrollY: true,
          click: true,
          pullDownRefresh: {
            threshold: 90,
            stop: 30
          },
          pullUpLoad: {
            threshold: 30
          }
        });
        // 当下拉距离达到 threshold 配置的值时触发
        bScrollInstance.on('pullingDown', pullingDownHandler);
        bScrollInstance.on('pullingUp', pullingUpHandler);
        bScrollInstance.on('scroll', scrollHandler);
}
function scrollHandler(e) {
        let y = e.y;
       // your code
       
        if(is_IOS_13_4()) {
            handleIOS_13_4_Shade(y);
        }
}
function pullingDownHandler(e) {
        // your code
}
function pullingUpHandler(e) {
      // your code 
     // 当数据全部加载完成之后记得调用closePullUp()函数 关闭上拉加载
 }
function is_IOS_13_4() {
        let verNum = 0;
        let reg = /OS (\d+[\_\d]+)/g;
        let isIos = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
        if(isIos) {
          let iosVer = navigator.appVersion;
          let ver = reg.exec(iosVer)[1];
          let verArr = ver.split('_');
          for(let i = 0; i < verArr.length; i++) {
            if(i !== 0) {
              verNum +=  parseInt(verArr[i]) * 1 / Math.pow(10,i);
            } else {
              verNum += parseInt(verArr[i]);
            }
          }
          verNum = Math.round(verNum * 100) / 100;
          console.log(verNum);
        }
        return isIos && verNum >= 13.4;
}
function handleIOS_13_4_Shade(y) {
        // 解决ios13.4版本下滚动到顶部时列表的抖动问题 -- 下滑
        if(bScrollInstance.movingDirectionY === -1 && (y < 0 && y > -20)) {
            bScrollInstance.scrollTo(0,0,0);
        }

         // 解决ios13.4版本下滚动到底部时列表的抖动问题 -- 上滑
        if (loadFinish && (y - bScrollInstance.maxScrollY) < 20) {
            bScrollInstance.scrollTo(0, bScrollInstance.maxScrollY, 0);
        }
}

@maomaoxiyu123
Copy link

  let isTouching = false; //是否正在触摸屏
  let scrollYBottom = 0; //滚动到底部的值
  let isPullingDown = false; //是否在下拉过程中,避免下拉后立刻回弹,保留回弹效果
  let isPullingUp = false; //是否在上拉过程中, 避免上拉后立刻回弹,保留回弹效果

  const ver = navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);
  //判断ios是否大于13.4
  const isIosVerLgThan1304 = ver && ver.length > 3 && ver[1] >= 13 && ver[2] >= 4; //判断ios是否大于13.4

  const oWrapper = document.getElementById("wrapper");

  const scroll = new BScroll("#wrapper", {});

  if (isIosVerLgThan1304) {
    scroll.on("scroll", (pos) => {
      //根据Y值判断是否下拉结束
      if (pos.y <= 0 && isPullingDown) isPullingDown = false;
      if (pos.y >= scrollYBottom && isPullingUp) isPullingUp = false;

      if (isTouching) return;

      //限制正常滑动过程中scroll顶部回弹
      if (!isPullingDown && pos.y >= 0) {
        scroll.scrollTo(0, 0, 0);
      }

      //限制正常滑动过程中scroll底部回弹
      if (!isPullingUp && scrollYBottom >= pos.y) {
        scroll.scrollYTo(0, scrollYBottom, 0);
      }
    });

    oWrapper.addEventListener("touchstart", () => {
      //每次触摸时重新计算滚动到底部Y值... 解决开启上拉加载后,内容高度会变
      scrollYBottom = scroll.wrapperHeight - scroll.scrollerHeight;
      isTouching = true;
    });
    oWrapper.addEventListener("touchend", () => {
      if (scroll.y > 0) isPullingDown = true; //保持下拉状态
      if (scroll.y < scrollYBottom) isPullingUp = true; //保持上拉状态
      isTouching = false;
    });
  }

上面是从我的react组件中剥离出来的逻辑(简化版),此段代码没测试过,大致逻辑是这样的。
注:自己封装的react组件中亲测有效,牺牲下13.

今天刚升级的iOS版本就坏了,昨天还好好的

就是iOS 13.4 才会出现的,我现在也遇到了,项目生产环境在用着。急!请问有解决办法吗

请问解决了么

@894046832
Copy link

测试:更新到2.0.4修复

@chenyulun
Copy link

测试:更新到2.0.4修复

不会是你的手机升级了ios14的原因吧

@fallenleavesguy
Copy link

测试:更新到2.0.4修复

没修复,而且很多浏览器都有问题,用的raf,并且关了回弹功能,滑得愉快还是弹

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests