javascript requestAnimationFrame最终位置永远不会确切

时间:2018-05-03 18:47:40

标签: javascript animation requestanimationframe

let pf = document.querySelectorAll('.pf');

for (let i of pf) {
  Object.assign(i.style, {
    left: '400px'
  })
}

function shiftLetters() {
  let start = performance.now();
  let dist = -400;
  let dur = 500;

  const logoAnimate = (timestamp) => {

    var runtime = timestamp - start
    var progress = Math.min(runtime / dur, 1)
    const position = progress * dist;

    if (runtime < dur) {
      for (let i = 0; i < pf.length; i++) {
        (function(i) {
          setTimeout(function() {
            pf[i].style.transform = `translate3d(${position}px,0,0)`
          }, 100 * i)
        })(i);
      }
      requestAnimationFrame(logoAnimate)
    }
  }
  requestAnimationFrame(logoAnimate)
}

document.getElementsByTagName('button')[0].addEventListener('click', shiftLetters);
#wrapper {
  display: flex;
  position: absolute;
  -webkit-transform: translate(-50%, 10%);
  transform: translate(-50%, 10%);
  top: 50%;
  left: 50%;
}

.pf {
  display: inline-block;
  position: relative;
  width: 100px;
  height: 100px;
  margin: 2px;
  background-color: red;
}

button {
  display: block;
  margin-top: 50px;
}
<div id="wrapper">
  <div class="pf"></div>
  <div class="pf"></div>
  <div class="pf"></div>
  <div class="pf"></div>
</div>
<button>animate</button>

当点击按钮时,我有4个元素,它们应该在dist变量的确切距离处结束。相反,它以随机整数结束,并且从不完全-400px,如我的dist变量-400中所述。必须简单。我已将变量写在范围之外等等。

1 个答案:

答案 0 :(得分:2)

原因是你从不应用最终的变换。当shiftLetters最后= {400} position大于runtime时,dur的最后一次迭代,因此您永远不会输入if语句并应用转换。下面稍微重构的代码。

&#13;
&#13;
let pf = document.querySelectorAll('.pf');

for (let i of pf) {
  Object.assign(i.style, {
    left: '400px'
  })
}

function shiftLetters() {
  let start = performance.now();
  let dist = -400;
  let dur = 500;

  const logoAnimate = (timestamp) => {

    var runtime = timestamp - start
    var progress = Math.min(runtime / dur, 1)
    const position = progress * dist;

    applyTransform(position);

    if (runtime < dur) {
      requestAnimationFrame(logoAnimate)
    }
  }
  requestAnimationFrame(logoAnimate)
}

function applyTransform(position) {
  for (let i = 0; i < pf.length; i++) {
    setTimeout(function() {
      pf[i].style.transform = `translate3d(${position}px,0,0)`
    }, 100 * i)
  }
}

document.getElementsByTagName('button')[0].addEventListener('click', shiftLetters);
&#13;
#wrapper {
  display: flex;
  position: absolute;
  -webkit-transform: translate(-50%, 10%);
  transform: translate(-50%, 10%);
  top: 50%;
  left: 50%;
}

.pf {
  display: inline-block;
  position: relative;
  width: 100px;
  height: 100px;
  margin: 2px;
  background-color: red;
}

button {
  display: block;
  margin-top: 50px;
}
&#13;
<div id="wrapper">
  <div class="pf"></div>
  <div class="pf"></div>
  <div class="pf"></div>
  <div class="pf"></div>
</div>
<button>animate</button>
&#13;
&#13;
&#13;