在D3中以可变速度对多线图进行动画处理

时间:2019-01-31 19:08:12

标签: d3.js

我正在尝试制作多条路径的动画,其中每条路径在通过后续部分时都会以可变的速度绘制。路径应同时开始绘制(但可以在不同时间结束)。我使用logical AND &&作为参考,但只画了一条线。

我分别绘制了每个路径和每个线段的长度,但是动画没有开始,并且我认为我在最后几行中无法正确访问速度。

this example以获得完整视图,但主要部分在下面。怎么了?

var lengthAt = [];
for (var i = 0; i < 3; i++) {

  start = i;
  end = i + 2;

  var path = svg.selectAll(".line")
    .data(lineData)
    .enter().append("path")
    .attr("d", function (d) { return line(d.values.slice(start, end)) })
    .style("stroke", "red")
    .style("stroke-width", .5)
   // .attr("class", "temppath")
   // .attr("visibility", "hidden");

  // get length at each segment 
  lengthAt.push([path["_groups"][0][0].getTotalLength(),
                 path["_groups"][0][1].getTotalLength()])
};

//svg.selectAll('.temppath').remove();
console.log({ lengthAt }) // looks good!

// Add the full path
var path = svg.selectAll(".line")
    .data(lineData)
    .enter()
    .append("path")
    .attr("d", function (d) { return line(d.values) })
    .style("stroke", "black")
    .attr('stroke-width', 2)
    .attr("fill", 'none');

// get the lengths of each path
var totalLength = [path["_groups"][0][0].getTotalLength(),
                   path["_groups"][0][1].getTotalLength()]

/////////////////////////////////////////////////////////////////////
/////////////////// START THE ANIMATION PROCESS /////////////////////

path.attr('stroke-dasharray', totalLength + " " + totalLength)
        .attr('stroke-dashoffset', totalLength)

var transitionFrom = path;

// start at 1 since no transition needed to first point
// iterate through "transitionFrom" and chain from point to 
// point, using the speed from the data.
for (var i = 1; i < 4; i++) {

  console.log(i)
  console.log(lengthAt[i - 1])
  lineData.forEach(function(d){ console.log(d.values[i].speed)})

  transitionFrom = transitionFrom.transition()
    .duration(function (d) { return d.values[i].speed })
    .ease(d3.easeLinear)
    .attr("stroke-dashoffset", lengthAt[i - 1] || 0)
}

1 个答案:

答案 0 :(得分:0)

此问题的解决方案分为两部分。首先,我重构为使用forEach()和each()而不是循环。独立/参数化的动画是通过使用链接的过渡完成的。

 // start the circle along the path
 var transitionFrom = circle.transition()
        .duration(eachGuy[1].speed)
        .attrTween("transform", getPath(mySegments[0].node()));

  // iterate through every segment and chain the transitions
  for (i = 1; i < 3; i++) {
    transitionFrom = transitionFrom.transition()
      .duration(eachGuy[i + 1].speed)
      .attrTween("transform", getPath(mySegments[i].node()))
  }

  // This is based off of Mike Bostock's example (linked below)
  function getPath(path) {
    var l = path.getTotalLength();
    return function () {
      return function (t) {
        var p = path.getPointAtLength(t * l);
        return "translate(" + p.x + "," + p.y + ")";
      };
    };
  };

完整的小提琴是here

资源: