jQuery 滑块动画无法正常工作

jQuery slider animation is not working properly

我正在制作一个博客模板,我在上面添加了一个 self-made jQuery 滑块,它使用递归 setTimeout() 进行无限幻灯片迭代。

幻灯片中的图像是并排的,幻灯片的工作方式如下:

  1. 第一张图片淡出并附加到其 parent 的最后位置。
  2. 所以第二张图片现在变成了第一张 child,同样的事情发生在它身上。
  3. 幻灯片以这种方式继续运行。

问题是,有时幻灯片放映会变得疯狂,并且多次出现所有图像同时淡出和淡入。几秒钟后,幻灯片又开始正常播放了。

请告诉我问题出在哪里。

JSFiddle

setTimeout(function run() {
  fade_out();
  setTimeout(run, 3000);
}, 3000);

// var first_child;
// setInterval(fade_out,3000);
// setInterval also causes the same problem

function fade_out() {
  first_child = $('.timeline-list li:first');
  first_child.fadeOut(1000);

  setTimeout(function() {
    $('.timeline-list').append(first_child);
    first_child.fadeIn();
  }, 1000);
}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.row {
  width: 1140px;
  margin: 0 auto;
}

.clearfix {
  zoom: 1;
}

.clearfix:before,
.clearfix:after {
  content: "";
  display: table;
}

.clearfix:after {
  clear: both;
}

.timeline-container {
  overflow: hidden;
  position: relative;
}

.timeline-title {
  text-align: center;
  font: 120%;
  color: #D35400;
  width: 200px;
  height: 125px;
  background-color: #fff;
  border: 1px solid #D35400;
  line-height: 130px;
}

.timeline-list {
  list-style: none;
  width: 1600px;
  height: 125px;
  position: absolute;
  left: 200px;
  top: 0;
  z-index: -1;
  margin-left: 2px;
}

.timeline-list li {
  width: 200px;
  height: 125px;
  background: #000;
  overflow: hidden;
  float: left;
  color: #fff;
  border-right: 1px solid #fff;
  line-height: 125px;
  text-align: center;
}
<section class="timeline">
  <div class="row">
    <div class="timeline-container clearfix">
      <div class="timeline-title">My Timeline</div>
      <ul class="timeline-list clearfix">
        <li>Image 1</li>
        <li>Image 2</li>
        <li>Image 3</li>
        <li>Image 4</li>
        <li>Image 5</li>
        <li>Image 6</li>
      </ul>
    </div>
  </div>
</section>
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>

向我的小朋友问好requestAnimationFrame

requestAnimationFrame是你的朋友

requestAnimationFrame的好处

  1. They are browser optimised, so they can operate in most cases at 60fps (aka the sweet spot for animation).
  2. Animations taking place in inactive tabs are stopped. Meaning if a user navigates away from your tab and you have an animation, it releases the stronghold it has on the CPU.
  3. Because of the aforementioned performance and respect, battery life and page responsiveness are better on low-end devices and mobile browsers.

如果您有在Javascript中执行动画的冲动,那么您可能已经使用了setTimeoutsetInterval来实现这一点。出于多种原因,这很糟糕,其中最大的一个原因是它们会降低访问者浏览器的性能并耗尽他们的小 phone 电池。

这两个函数的问题很简单。他们不了解使用浏览器和在正确的时间绘制内容的微妙之处。他们不知道页面其余部分发生了什么。这些品质使它们在为动画提供动力时效率非常低,因为它们经常请求 repaint/update 而您的浏览器根本没有准备好执行。您通常会遇到跳帧和其他可怕的副作用。

读这个Article and here for requestAnimationFrame DOC

function fade_out() {
  first_child = $('.timeline-list li:first');
  first_child.fadeOut(1000);

  setTimeout(function() {
    $('.timeline-list').append(first_child);
    first_child.fadeIn();
    requestAnimationFrame(fade_out);
  }, 3000);
}
requestAnimationFrame(fade_out);
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.row {
  width: 1140px;
  margin: 0 auto;
}

.clearfix {
  zoom: 1;
}

.clearfix:before,
.clearfix:after {
  content: "";
  display: table;
}

.clearfix:after {
  clear: both;
}

.timeline-container {
  overflow: hidden;
  position: relative;
}

.timeline-title {
  text-align: center;
  font: 120%;
  color: #D35400;
  width: 200px;
  height: 125px;
  background-color: #fff;
  border: 1px solid #D35400;
  line-height: 130px;
}

.timeline-list {
  list-style: none;
  width: 1600px;
  height: 125px;
  position: absolute;
  left: 200px;
  top: 0;
  z-index: -1;
  margin-left: 2px;
}

.timeline-list li {
  width: 200px;
  height: 125px;
  background: #000;
  overflow: hidden;
  float: left;
  color: #fff;
  border-right: 1px solid #fff;
  line-height: 125px;
  text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="timeline">
  <div class="row">
    <div class="timeline-container clearfix">
      <div class="timeline-title">My Timeline</div>
      <ul class="timeline-list clearfix">
        <li>Image 1</li>
        <li>Image 2</li>
        <li>Image 3</li>
        <li>Image 4</li>
        <li>Image 5</li>
        <li>Image 6</li>
      </ul>
    </div>
  </div>
</section>
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>