无缝轮播滚动,js代码异步,出了点小问题

发布于 2022-09-07 20:25:23 字数 1056 浏览 29 评论 0

要轮播5张图 ,布置 5->1->2->3->4->5->1 7张图 要实现无缝
实际思路上就是最后一张滚到第一张实际是顺着滚,动画结束再取消transition切回第一张再附加transition
现在我遇到这个个问题

/...5->1执行的代码(有滚动动画).../
     if (newLeft === -3600) { //滚到第7张图时的left,执行回滚
          setTimeout(function () {
            list.style.transition = 'none'; //取消动画
            list.style.left = -600 + 'px'; //瞬间回滚
            list.style.transition = 'left 2s linear';//恢复动画 //但是这句话回滚的时候会生效是为什么
          },2000)
      }

这么写回滚的时候动画会生效
必须要用下面的写法,第二个计时器必须大于2000几个毫秒才满足需求,
为什么会发生这种事情,计时器里面回调函数应该是同步的呀, list.style.left = -600 + 'px';不执行完后面应该是不会设置动画的呀?

if (newLeft === -3600) {
      setTimeout(function () {
        list.style.transition = 'none';
        list.style.left = -600 + 'px';
      },2000)
      setTimeout(function () {
                list.style.transition = 'left 2s linear';
      },2020)
}

这里我发现:间隔时间1-4秒基本没用给,间隔10ms偶尔会出现回滚动画,设置20ms基本没问题
实际上还是刚刚的问题,js是单线程,会阻塞,2000ms执行的代码如果不执行完,2010ms是不会把异步代码拿来执行的,如果执行完了,那么我这个回滚应该是没有动画的。求大神解释一下

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

内心旳酸楚 2022-09-14 20:25:23

浏览器会在一个特定的点去执行渲染,在那之前的操作是没有中间态的!

list.style.left = 0 + 'px';

// 某一时刻 浏览器渲染

// 浏览器执行js
list.style.left = 1 + 'px';
list.style.left = 2 + 'px';
list.style.left = 3 + 'px';
list.style.left = 4 + 'px';

// 某一时刻 浏览器渲染

在两次渲染间,浏览器只知道 list.style.left 从 0 变为 4px 这个事实, 他不知道也不关心你到 4 中间发生了什么, 你可以是1个px 累加,或先到100再到4. 浏览器看到就是上一次渲染是0,这次是4.

所以

list.style.transition = 'none'; 
list.style.left = -600 + 'px';
list.style.transition = 'left 2s linear';

在浏览器看来就是:

list.style.left = -600 + 'px';
list.style.transition = 'left 2s linear';

解决办法是在需要被感知状态的地方让浏览器进行一次渲染, setTimeout 就可以达到这个效果,还有常见的访问 offsetWidth 等属性触发一次 reflow.

方案一:

list.style.transition = 'none'; 
list.style.left = -600 + 'px';

// 触发 reflow
list.offsetWidth;

list.style.transition = 'left 2s linear';

方案二:


setTimeout(function () {
  list.style.transition = 'none';
  list.style.left = -600 + 'px';

  // 延迟这部分脚本执行, 让浏览器先渲染当前帧
  setTimeout(() => {
     list.style.transition = 'left 2s linear';
  })
},2000)
白日梦 2022-09-14 20:25:23

很感谢liximomo的答案,我在这里就第二个小问题做个补充把
浏览器的js引擎线程和ui渲染线程互斥,js执行时会阻塞页面的渲染
当第二个计时器函数执行的时候,如果此时第一个计时器中的代码导致的reflow还没完成,那么它会暂停。执行第二个计时器的代码,也就是list.style.transition = 'left 2s linear';
然后再启动第一个reflow工作,此时回滚动画就产生了
所以间隔时间如果比较小的话,就会导致回滚动画现象的产生

瞳孔里扚悲伤 2022-09-14 20:25:23

增加监听事件

// Safari 3.1 到 6.0 代码
document.getElementById("myDIV").addEventListener("webkitTransitionEnd", myFunction);

// 标准语法
document.getElementById("myDIV").addEventListener("transitionend", myFunction);

myFunction (){

    if(n>=5){ // 用n记录当前图片的位置
            //瞬间回滚
    }else if (n==0){
            //瞬间回滚
    }

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文