简体   繁体   English

d3过渡中圆的碰撞/重叠检测

[英]Collision/overlap detection of circles in a d3 transition

I'm using d3 to animate a route (path) on a map. 我正在使用d3为地图上的路径(路径)设置动画。 When the route reaches a point along the route I'd like to popup some information. 当路线到达路线上的某个点时,我想弹出一些信息。

Most of my code is based on the following example. 我的大多数代码都基于以下示例。 http://bl.ocks.org/mbostock/1705868 . http://bl.ocks.org/mbostock/1705868 I'm really just trying to determine if there is a way to detect when the transitioning circle collides or overlaps any of the stationary circles in this example. 我真的只是想确定是否有一种方法来检测过渡圆在这个例子中何时碰撞或重叠任何静止圆圈。

You can detect collision in your tween function. 您可以检测补间功能中的冲突 Define a collide function to be called from inside the tween function as follows: 定义要从补间函数内部调用的collide函数,如下所示:

function collide(node){
    var trans = d3.transform(d3.select(node).attr("transform")).translate,
      x1 = trans[0],
      x2 = trans[0] + (+d3.select(node).attr("r")),
      y1 = trans[1],
      y2 = trans[1] + (+d3.select(node).attr("r"));

  var colliding = false;
  points.each(function(d,i){
    var ntrans = d3.transform(d3.select(this).attr("transform")).translate,
      nx1 = ntrans[0],
      nx2 = ntrans[0] + (+d3.select(this).attr("r")),
      ny1 = ntrans[1],
      ny2 = ntrans[1] + (+d3.select(this).attr("r"));


      if(!(x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1))
        colliding=true;
  })

  return colliding;
}

Where points are the stationary points, and node is the transitioning element. 其中points是静止点, node是过渡元素。 What collide does is check whether node overlaps with any of the points (as shown in collision detection example here ). collide作用是检查node是否与任何node 重叠 (如此处的碰撞检测示例所示)。

Because we need the node to be passed to the tween function, we replace attrTween used in Mike's example, with tween : 因为我们需要将node传递给补间函数,所以我们将替换Mike示例中使用的attrTweentween

circle.transition()
      .duration(10000)
      .tween("attr", translateAlong(path.node()))
      .each("end", transition);

Finally, the tween function calling our collide : 最后,调用我们collide的补间函数:

function translateAlong(path) {
  var l = path.getTotalLength();
  return function(d, i, a) {
    return function(t) {
      var p = path.getPointAtLength(t * l);

      d3.select(this).attr("transform","translate(" + p.x + "," + p.y + ")");

      if(collide(this))
        d3.select(this).style("fill", "red")
       else
        d3.select(this).style("fill", "steelblue")
    };
  };
}

See the full demo here 请在此处查看完整演示

The easiest way is to just check how "close" the transitioning circle is to the other points. 最简单的方法是检查过渡圆圈与其他点的“接近”程度。

var pop = d3.select("body").append("div")
    .style("position","absolute")
    .style("top",0)
    .style("left",0)
    .style("display", "none")
    .style("background", "yellow")
    .style("border", "1px solid black");

// Returns an attrTween for translating along the specified path element.
function translateAlong(path) {
  var l = path.getTotalLength();
  var epsilon = 5;
  return function(d, i, a) {
    return function(t) {
      var p = path.getPointAtLength(t * l);
      points.forEach(function(d,i){
        if ((Math.abs(d[0] - p.x) < epsilon) && 
            (Math.abs(d[1] - p.y) < epsilon)){
          pop.style("left",d[0]+"px")
            .style("top",d[1]+20+"px")
            .style("display","block")
            .html(d);
          return false;
        }
      })
      return "translate(" + p.x + "," + p.y + ")";
    };
  };
}

The faster the circle moves the greater your epsilon will need to be. 圆圈移动得越快,你的epsilon就越大。

Example here . 这里的例子。

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM