【问题标题】:Animating a queue of elements are skipping to final element动画元素队列正在跳到最终元素
【发布时间】:2019-07-27 17:06:00
【问题描述】:

CodePen

规则:

  • 每次点击都会添加一个<progress> 元素。
  • 每个进度条都会充满动画。
  • 动画在前一个完成之前不会开始。

问题:

如果您快速单击,它只会为最后一个progress 栏设置动画。并且动画应该一个一个地发生直到完成。

问题:

快速点击时,为什么动画乱序?

HTML:

<div class="container">
  <div class="add-progress-container">
    <input class="input-seconds" type="number" min="1" max="10" value="1">
    <button class="add-progress">Add progress</button>
  </div>  
  <div class="progress-container"></div>
</div>

JS:

const container = document.querySelector('.progress-container');
const inputSeconds = document.querySelector('.input-seconds');
const addBtn = document.querySelector('.add-progress');
let animating = false;


function animateProgress(duration, el) {
  const intervalId = setInterval(() => {
    if(el.value >= el.max) {
      animating = false;
      window.clearInterval(intervalId);
      console.log('finished');
      checkQueue();
      return;
    }

    el.value += el.max/duration;
  }, 1000);
} 


function getSeconds() {
  return parseInt(inputSeconds.value, 10);
}

let progressCount = 0;

function createProgress() {
  const template = `<progress data-progress="${progressCount}" value="0" max="100"></progress>`;
  container.innerHTML += template;
  const el = document.querySelector(`[data-progress="${progressCount}"]`);
  progressCount++;
  return el;
}

let queue = [];
function addProgress() {
  const el = createProgress()
  queue.push(el);
  checkQueue();
}

function checkQueue() {
  if(queue.length && !animating) {
    animating = true;
    animateProgress(getSeconds(), queue.shift());
  }  
}

addBtn.addEventListener('click', addProgress);

【问题讨论】:

  • 你期待它应该是怎样的?无论是否快速点击,都一一动画化?
  • 是的,一个一个,即使是快速点击
  • 注意:您的选择器中缺少右方括号。
  • @trincot 很好,但不是什么破坏了它:(

标签: javascript html animation


【解决方案1】:

innerHTML+= 分配将重新创建容器元素中的所有先前元素,这意味着您对其他 progress 元素的引用不再是此分配创建的实际元素。

你应该像这样添加一个新的进度元素:

function createProgress() {
  const el = document.createElement("progress");
  el.setAttribute("data-progress", progressCount);
  el.setAttribute("value", 0);
  el.setAttribute("max", 100);
  container.appendChild(el);
  return el;
}

正如 Makyuu 在下面评论的那样,各个进度元素的步数仅在其动画开始时才计算。这意味着如果您更改输入值,它也将应用于先前创建的元素(当它们尚未开始动画时)。

如果打算使用元素创建时指示的步骤数,则修改代码中的两行:

queue.push([getSeconds(), el]);

和:

animateProgress(...queue.shift());

【讨论】:

  • @MatthewHarwood 不确定你是否知道。但是在您将它们排队之后,您会注意到progressBar 的增加是基于当前值而不是输入时的值。
  • 如果这种行为不是故意的,请参阅我的回答。
猜你喜欢
  • 1970-01-01
  • 2021-05-17
  • 1970-01-01
  • 2023-03-13
  • 2015-09-03
  • 2017-04-27
  • 2015-10-29
  • 2023-04-02
  • 1970-01-01
相关资源
最近更新 更多