如何正确暂停 requestAnimationFrame 幻灯片放映?

How to properly paused a requestAnimationFrame slideshow?

我正在尝试学习如何使用 requestAnimationFrame API 来使用 js 控制动画,在这种情况下,我在幻灯片的上下文中使用它,幻灯片可以正常滑动,它甚至有延迟功能,但我不知道如何正确暂停和恢复它,大多数时候当我点击暂停然后恢复时元素会被冻结,任何人都可以解释为什么会发生这种情况以及正确暂停和恢复的解决方案是什么英国皇家空军。谢谢大家

这是我的代码:

var elems = document.querySelectorAll('.slider');
var total = elems.length;
var opacity = 1;
var dist = 300;
var duration = 1000;
var delay = 2000;
var index = 0;
var startTime;
var slideRaf;

function startRaf(timestamp) {
  var timestamp = timestamp;
  var runtime = timestamp - startTime;
  if (runtime <= duration) {
    var progress = Math.min((runtime / duration), 1);
    if (index === 0) {
      elems[index].style.transform = 'translate3d(' + (dist * progress) + 'px, 0px, 0px)';
      elems[index].style.opacity = (opacity * progress);
      elems[total - 1].style.transform = 'translate3d(' + (dist - (dist * progress)) + 'px, 0px, 0px)';
      elems[total - 1].style.opacity = opacity - (opacity * progress);
    } else {
      elems[index].style.transform = 'translate3d(' + (dist * progress) + 'px, 0px, 0px)';
      elems[index].style.opacity = (opacity * progress);
      elems[index - 1].style.transform = 'translate3d(' + (dist - (dist * progress)) + 'px, 0px, 0px)';
      elems[index - 1].style.opacity = opacity - (opacity * progress);
    }
  } else if (runtime > delay) {
    if (index < (total - 1)) {
      index += 1;
    } else {
      index = 0;
    }
    startTime = timestamp;
  }
  slideRaf = requestAnimationFrame(startRaf);
}

requestAnimationFrame(function (timestamp) {
  startTime = timestamp;
  startRaf(timestamp);
});

document.getElementById('start').addEventListener('click', function () {
  requestAnimationFrame(startRaf);
}, false);

document.getElementById('pause').addEventListener('click', function () {
  cancelAnimationFrame(slideRaf);
}, false);
* {
  box-sizing: border-box;
}
html, body {
  padding: 0;
  margin: 0;
  font-family: sans-serif;
  background: yellow;
  overflow: hidden;
}
.slider {
  position: relative;
  width: 150px;
  height: 50px;
  left: 50%;
  margin-left: -75px;
  background: rgb(168, 39, 219);
  opacity: 0;
}
#start {
  position: absolute;
  top: 20px;
  left: 20px;
}
#pause {
  position: absolute;
  top: 50px;
  left: 20px;
}
<div class="slider"></div>
<div class="slider"></div>
<div class="slider"></div>
<div class="slider"></div>
<div class="slider"></div>

<button id="start">START</button>
<button id="pause">PAUSE</button>

我终于明白了,现在它可以暂停和恢复而不会在视图中卡住某些元素,我使用一个变量来通知 pause/resume 状态(通过这样做我排除了 cancelAnimationFrame),现在它也滑入了准确的距离,但需要注意的是代码有些混乱,动画无法在过渡过程中暂停,因此我确保在用户点击暂停按钮后,最后一个元素仍会滑向目标距离,但在那之后停止继续,直到用户点击开始按钮恢复幻灯片放映。这是新代码(如果您有更好的替代方案,请随时在此 post 中分享您的解决方案):

var elems = document.querySelectorAll('.slider');
var total = elems.length;
var opacity = 1;
var dist = 300;
var duration = 1000;
var delay = 2000;
var index = 0;
var startTime;
var slideRaf;
var clear = 0;
var pause = false;

function startRaf(timestamp) {
  var timestamp = timestamp;
  var runtime = timestamp - startTime;
  var progress = Math.min((runtime / duration), 1);
  if (index === 0) {
    var last = total - 1;
  } else {
    var last = index - 1;
  }
  if (runtime <= duration) {
    elems[index].style.transform = 'translate3d(' + (dist * progress) + 'px, 0px, 0px)';
    elems[index].style.opacity = (opacity * progress);
    elems[last].style.transform = 'translate3d(' + (dist - (dist * progress)) + 'px, 0px, 0px)';
    elems[last].style.opacity = (opacity - (opacity * progress));
  } else if (runtime > delay) {
    elems[index].style.transform = 'translate3d(' + dist + 'px, 0px, 0px)';
    elems[index].style.opacity = opacity;
    elems[last].style.transform = 'translate3d(0px, 0px, 0px)';
    elems[last].style.opacity = 0;
    if (pause === false) {
      if (index < (total - 1)) {
        index += 1;
      } else {
        index = 0;
      }
      clear = 0;
      startTime = timestamp;
    }
  } else {
    if (clear === 0) {
      elems[index].style.transform = 'translate3d(' + dist + 'px, 0px, 0px)';
      elems[index].style.opacity = opacity;
      elems[last].style.transform = 'translate3d(0px, 0px, 0px)';
      elems[last].style.opacity = 0;
      clear = 1;
    }
  }
  slideRaf = requestAnimationFrame(startRaf);
}

requestAnimationFrame(function (timestamp) {
  startTime = timestamp;
  startRaf(timestamp);
});

document.getElementById('start').addEventListener('click', function () {
  pause = false;
  requestAnimationFrame(startRaf);
}, false);

document.getElementById('pause').addEventListener('click', function () {
  pause = true;
}, false);
* {
  box-sizing: border-box;
}
html, body {
  padding: 0;
  margin: 0;
  font-family: sans-serif;
  background: yellow;
  overflow: hidden;
}
.slider {
  position: relative;
  width: 150px;
  height: 50px;
  left: 50%;
  margin-left: -187px;
  background: rgb(168, 39, 219);
  opacity: 0;
}
#start {
  position: absolute;
  top: 20px;
  left: 20px;
}
#pause {
  position: absolute;
  top: 50px;
  left: 20px;
}
<div id="slider" class="slider"></div>
<div id="slider2" class="slider"></div>
<div id="slider3" class="slider"></div>
<div id="slider4" class="slider"></div>
<div id="slider5" class="slider"></div>
<div id="slider6" class="slider"></div>
<div id="slider7" class="slider"></div>
<div id="slider8" class="slider"></div>
<div id="slider9" class="slider"></div>
<div id="slider10" class="slider"></div>
<div id="slider11" class="slider"></div>
<div id="slider12" class="slider"></div>
<div id="slider13" class="slider"></div>
<div id="slider14" class="slider"></div>
<div id="slider15" class="slider"></div>

<button id="start">START</button>
<button id="pause">PAUSE</button>