代码之家  ›  专栏  ›  技术社区  ›  Armeen Moon

设置元素队列的动画将跳转到最终元素

  •  0
  • Armeen Moon  · 技术社区  · 6 年前

    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);
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   trincot Jakube    6 年前

    这个 innerHTML+= 赋值将在container元素中重新创建所有以前的元素,这意味着您对其他元素的引用 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;
    }
    

    正如makyou在下面评论的那样,单个进度元素的步骤数只有在其动画开始时才会执行。这意味着,如果更改输入值,它也将应用于以前创建的元素(当它们尚未开始设置动画时)。

    如果打算使用所示步骤的数量 在元素创建时 ,然后修改代码中的两行:

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

    以及:

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