如何正确暂停requestAnimationFrame幻灯片?

时间:2018-04-12 00:22:40

标签: javascript timing requestanimationframe

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

下面'我的代码:



callback

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);
&#13;
* {
  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;
}
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

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

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>