如何在 d3.js 中检测当前元素的位置并取消动画

How to detect current element's position and cancel an animation in d3.js?

本文关键字:元素 位置 动画 取消 d3 js 检测      更新时间:2023-09-26

我有一个使用 jQuery 的 Web 应用程序,我正在更新它以使用 d3.js 代替。这是一个游戏,其中有一个动画的瓷砖并从屏幕顶部掉落,直到它撞到"地板"或其他物体上。

我能够创建动画,使元素从屏幕的顶部到底部以线性形式落下,如下所示(mcve):

var wh = window.innerHeight - 40;
d3.select("#tile")
  .transition()
  .duration(2000)
  .style("top", wh + "px")
  .ease("linear");
#tile {
  width:40px;
  height:40px;
  position:absolute;
  top:0px;
  left:0px;
  background:#336699;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="tile"></div>

如果没有任何对象挡住,这工作正常,但如果有,我发现两个问题:

  • 使用 jQuery,我将animate()step 方法一起使用,这样我就可以获取元素的当前位置,从而检测与其他元素的冲突。在 d3.js 中是否有等同于 transition()step()

  • 一旦检测到碰撞,如何取消动画以使元素停止移动?(类似于jQuery中的stop())。

在网上做一些研究,我发现我可以创建一个持续时间为 0 的空过渡,这将回答第二点,但我想知道是否有更直接的方法。

如果您编写自己的 tween 函数,则可以完全控制转换。 在每次迭代中,您可以检查冲突并在必要时取消。

var wh = window.innerHeight - 40;
d3.select("#tile")
  .transition()
  .duration(2000)
  .ease("linear")
  .tween("fall", function() {
    var i = d3.interpolateNumber(0, wh);
    var self = d3.select(this);
    return function(t) {
      var isCollision = (t > 0.5); // some condition to cancel
      if (isCollision) {
        self.transition(); // cancel transition
      } else {
        self.style("top", i(t) + "px");  // continue falling
      }
    };
});
#tile {
  width:40px;
  height:40px;
  position:absolute;
  top:0px;
  left:0px;
  background:#336699;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="tile"></div>