javascript - 使用 D3.js,如何检测何时到达动画线上的点?

标签 javascript d3.js

使用 D3 我想检测我的动画线何时改变方向(或到达一个点),并在恰好时间点附加一个圆圈。因此,一个圆圈将一次附加,而不是所有圆圈,这就是当前正在发生的事情。

var points = [
  [480, 200],
  [580, 400],
  [680, 100],
  [780, 300],
  [180, 300],
  [280, 100],
  [380, 400]
];

var path = svg.append("path")
    .data([points])
    .attr("d", d3.svg.line()
    .tension(0) ); //); // Catmull–Rom 
    //.interpolate("cardinal-closed"));

var totalLength = path.node().getTotalLength();

path
    .attr("stroke-dasharray", totalLength + " " + totalLength)
    .attr("stroke-dashoffset", totalLength)
    .transition()
    .duration(10000)
    .ease("linear")
    .attr("stroke-dashoffset", 0);


svg.selectAll(".point", function(d,i){
        console.log(d,i)
    })
    .data(points)
    .enter().append("circle")
    .transition()
    .duration(2000)
    .ease("linear")
    .style("fill", "url(#image)")
    .attr("r", 20)
    .attr("transform", function(d) { return "translate(" + d + ")"; })

FIDDLE

我尝试测量最后一个 x 和 y 与之前的 x 和 y 的对比,但如果它们都继续沿正方向或负方向移动,则不容易发现差异。我还需要测量斜率变化。我希望有更聪明的方法?

我尝试测量以查看 newX 和 oldX 之间的差异是否保持不变,但它不起作用 :( https://jsfiddle.net/hs5a9z5a/3/

最佳答案

要知道线条何时改变方向(即击中数据点),您需要控制 stroke-dashoffset 上的转换功能。这就是我的做法(我试着很好地评论它,如果您有任何问题,请告诉我):

path
  .attr("stroke-dasharray", totalLength + " " + totalLength)
  .attr("stroke-dashoffset", totalLength)
  .transition()
  .duration(10000)
  .ease("linear")
  .tween("myTween", function() {
    var i = d3.interpolate(totalLength, 0);
    var self = d3.select(this);
    return function(t) {
        // current position of stroke-dashoffset     
        var len = i(t),
        // current position with respect to line length of stroke-dashoffset
        per = (1 - len / totalLength) * totalLength,
        // pixel position of stroke-dashoffset
        p = self.node().getPointAtLength(per);

      // loop our points and look for hit detection
      points.forEach(function(d) {
        // are we one a point?
        if (Math.abs(p.x - d[0]) < 1 && Math.abs(p.y - d[1]) < 1) {
          console.log("point hit");
        }
      });

      // apply stroke-dashoffset
      self.attr("stroke-dashoffset", len);
    };
  });

运行示例:

var points = [
  [480, 200],
  [580, 400],
  [680, 100],
  [780, 300],
  [180, 300],
  [280, 100],
  [380, 400]
];

var svg = d3.select("body").append("svg")
  .attr("width", 960)
  .attr("height", 500);


var path = svg.append("path")
  .data([points])
  .attr("d", d3.svg.line()
    .tension(0)); //); // Catmull–Rom 
//.interpolate("cardinal-closed"));

var totalLength = path.node().getTotalLength();

path
  .attr("stroke-dasharray", totalLength + " " + totalLength)
  .attr("stroke-dashoffset", totalLength)
  .transition()
  .duration(10000)
  .ease("linear")
  .tween("myTween", function() {
    var i = d3.interpolate(totalLength, 0);
    var self = d3.select(this);
    return function(t) {
      var len = i(t),
        per = (1 - len / totalLength) * totalLength,
        p = self.node().getPointAtLength(per);

      points.forEach(function(d) {
        if (Math.abs(p.x - d[0]) < 1 && Math.abs(p.y - d[1]) < 1) {
          console.log("point hit");
        }
      });
      
      self.attr("stroke-dashoffset", i(t));
    };
  });




/*
svg.selectAll(".point", function(d,i){
		//console.log(d,i)
	})
	.data(points)
	.enter().append("circle")
	.transition()
	.duration(2000)
	.ease("linear")
	.style("fill", "url(#image)")
	.attr("r", 20)
	.attr("transform", function(d) { return "translate(" + d + ")"; })
    
var circle = svg.append("circle")
	.attr("r", 13)
	.attr("transform", "translate(" + points[0] + ")");

transition();

function transition() {
	circle.transition()
	.duration(10000)
	.attrTween("transform", translateAlong(path.node()))
	//.each("end", transition);
	.each("end");
}

// Returns an attrTween for translating along the specified path element.
function translateAlong(path) {
  var l = path.getTotalLength();
  return function(d, i, a) {
    return function(t) {
      var p = path.getPointAtLength(t * l);
      return "translate(" + p.x + "," + p.y + ")";
    };
  };
}
*/
path {
  fill: none;
  stroke: #000;
  stroke-width: 3px;
}

circle {
  fill: url('http://www.e-pint.com/epint.jpg');
  fill: steelblue;
  /stroke: #fff;
  //stroke-width: 3px;
}
<script src="http://d3js.org/d3.v3.js"></script>

<svg id="mySvg" width="80" height="80">
  <defs id="mdef">
    <pattern id="image" x="0" y="0" height="40" width="40">
      <image x="0" y="0" width="40" height="40" xlink:href="http://www.e-pint.com/epint.jpg"></image>

    </pattern>
  </defs>
</svg>
<div id="line"></div>

关于javascript - 使用 D3.js,如何检测何时到达动画线上的点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40937535/

相关文章:

javascript - 使用 D3.js 创建矩形图表

javascript - Chrome 扩展程序通过 tabId 进行 WebRequest 过滤不起作用?

javascript - 从可视化中制作静态图像

javascript - 在 d3 图中的 <g> 元素上触发悬停事件

javascript - 以前我从谷歌驱动器渲染图像,现在我需要从本地路径渲染它。如何在 Reactjs 中渲染 const 变量中的图像?

javascript - d3.js 的多行

javascript - 在 SVG 元素上触发点击事件

php - 如果我的网站被盗,通知我的代码

javascript - 使用 TypeScript 时如何创建特定的 JS 包?

javascript - 在 react.js 中单击按钮时添加类