如何限制动画掉落立方体的总数并使它们按添加顺序进行动画处理?

How to limit the number of total animated drop cubes and make them animate by their added order?

当我们点击这个添加按钮时,我们将添加一个新的立方体,它会立即掉落,但如果我们快速点击它,就会有太多立方体掉落。我想限制动画掉落立方体的总数。

例如,即使我们快速点击按钮并向页面添加了 10 个立方体,也只有两个立方体在掉落,其他的必须等到它们完成。

例如,第3个和第4个方块会在第1个和第2个方块完成后开始掉落。

我在想也许我们可以有一个全局变量来表示动画立方体的总数,++ 和 -- 当一个新的立方体开始和结束动画时,使用 setInterval 检查变量是否小于 2,但这不能使动画基于立方体的创建顺序。我可以知道如何解决这个问题吗?非常感谢!

var btn = document.getElementById('add');
var container = document.getElementById('cubes-container');
var cubeId = 0;
btn.addEventListener('click', addCube);

var currentAnimateCount = 0;

function dropCube(cube) {
  var pos = 0;
  let intervalId = setInterval(function() {
    if (pos == 200) {
      clearInterval(intervalId);
    } else {
      pos++;
      cube.style.top = pos + "px";

    }
  }, 1);

}

function addCube() {
  let cube = document.createElement('div');
  let cubeContainer = document.createElement('div');
  cube.className = 'cube';
  cube.id = cubeId;
  cube.innerHTML = cube.id;
  cubeId++;
  cubeContainer.className = 'cube-container';
  cubeContainer.append(cube);
  container.append(cubeContainer);
  let pos = 0;
  dropCube(cube)


}
#cubes-container {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
}

.cube-container {
  position: relative;
  height: 30px;
}

.cube {
  width: 30px;
  height: 30px;
  background-color: orange;
  text-align: center;
  display: grid;
  align-items: center;
  justify-items: center;
  position: absolute;
}
<button id="add">add new</button>
<div id="cubes-container">
</div>

考虑以下示例。它使用 jQuery 而不是 JavaScript。它可以类似地编写脚本。

$(function() {
  function addCube(target) {
    var i = $(".cube").length;
    var container = $("<div>", {
      class: "cube-container"
    }).appendTo(target);
    $("<div>", {
      class: "cube",
      id: "cube-" + i
    }).html(i).appendTo(container);
    return container;
  }

  function dropCube(cube) {
    $(cube).addClass("falling").animate({
      top: "200px"
    }, 2000, function() {
      $(cube).removeClass("falling");
      if (cubes.length && $(".falling").length < 2) {
        dropCube(cubes.shift());
      }
    });
  }

  var cubes = [];

  $("#add").click(function() {
    cubes.push(addCube("#cubes-container"));
    if ($(".falling").length < 2) {
      dropCube(cubes.shift());
    }
  });
});
/*
var btn = document.getElementById('add');
var container = document.getElementById('cubes-container');
var cubeId = 0;
btn.addEventListener('click', addCube);

var currentAnimateCount = 0;

function dropCube(cube) {
  var pos = 0;
  let intervalId = setInterval(function() {
    if (pos == 200) {
      clearInterval(intervalId);
    } else {
      pos++;
      cube.style.top = pos + "px";
    }
  }, 1);

}

function addCube() {
  let cube = document.createElement('div');
  let cubeContainer = document.createElement('div');
  cube.className = 'cube';
  cube.id = cubeId;
  cube.innerHTML = cube.id;
  cubeId++;
  cubeContainer.className = 'cube-container';
  cubeContainer.append(cube);
  container.append(cubeContainer);
  let pos = 0;
  dropCube(cube)
}
*/
#cubes-container {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
}

.cube-container {
  position: relative;
  height: 30px;
}

.cube {
  width: 30px;
  height: 30px;
  background-color: orange;
  text-align: center;
  display: grid;
  align-items: center;
  justify-items: center;
  position: absolute;
  top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="add">add new</button>
<div id="cubes-container"></div>

使用数组,您可以 .shift() 数组的第一项。还向掉落的物品添加 Class 可以让您计算掉落的物品。我喜欢使用 Animate,因为它允许在动画完成时进行回调,因此您可以检查下一个项目。

JavaScript

更新

var btn = document.getElementById('add');
var container = document.getElementById('cubes-container');
var cubes = [];
btn.addEventListener('click', function(event) {
  cubes.push(addCube());
  if (document.getElementsByClassName("falling").length < 2) {
    dropCube(cubes.shift());
  }
});

function dropCube(cube) {
  var pos = 0;
  cube.classList.add("falling");
  var intervalId = setInterval(function() {
    if (pos == 200) {
      clearInterval(intervalId);
      cube.classList.remove("falling");
      if (document.getElementsByClassName("falling").length < 2 && cubes.length) {
        dropCube(cubes.shift());
      }
    } else {
      pos++;
      cube.style.top = pos + "px";
    }
  }, 1);
}

function addCube() {
  let cube = document.createElement('div');
  let cubeContainer = document.createElement('div');
  cube.className = 'cube';
  cube.id = document.getElementsByClassName("cube").length;
  cube.innerHTML = cube.id;
  cubeContainer.className = 'cube-container';
  cubeContainer.append(cube);
  container.append(cubeContainer);
  return cubeContainer;
}
#cubes-container {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
}

.cube-container {
  position: relative;
  height: 30px;
}

.cube {
  width: 30px;
  height: 30px;
  background-color: orange;
  text-align: center;
  display: grid;
  align-items: center;
  justify-items: center;
  position: absolute;
  top: 0;
}
<button id="add">add new</button>
<div id="cubes-container"></div>