【问题标题】:D3.js tweening forward and backward to a specific pointD3.js 前后补间到特定点
【发布时间】:2017-04-04 20:56:24
【问题描述】:

我刚开始在 D3 中使用 Tweening,一开始看起来很容易,但现在我正在努力在我当前的代码中实现这一点:

  • 补间到特定点,例如:从 0,0 到 lineData[4]
  • 从 lineData[4] 补间回到点 0,0

(可能使用按钮来控制)

这是我目前的代码:https://jsfiddle.net/uozko2bw/2/

//The data for our line
var lineData = [ 
{ "x": 1,   "y": 5},  { "x": 20,  "y": 20},
{ "x": 40,  "y": 10}, { "x": 60,  "y": 40},
{ "x": 80,  "y": 5},  { "x": 100, "y": 60}];

var lineFunction = d3.line()
 .x(function(d) { return d.x; })
 .y(function(d) { return d.y; })
 .curve(d3.curveCardinal);

//The SVG Container
var svgContainer = d3.select("body").append("svg")
    .attr("width", 200)
    .attr("height", 200);

//The line SVG Path we draw
var lineGraph = svgContainer.append("path")
 .attr("d", lineFunction(lineData))
 .attr("stroke", "blue")
 .attr("stroke-width", 2)              
 .attr("fill", "none");

 var circle = svgContainer.append("circle")
  .attr("r", 5)
  .attr("transform", "translate(" + lineData[0].x + "," + lineData[0].y + 
 ")");

 transition();

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

 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 + ")";
   };
 };
}

【问题讨论】:

    标签: javascript d3.js data-visualization


    【解决方案1】:

    interpolator 中的 t 通常从 0 变为 1:

    然后将为过渡的每一帧调用返回的插值器,按顺序通过缓动时间 t,通常在 [0, 1] 范围内。

    因此,您可以简单地调用另一个插值器,并将 t 从 1 变为 0:

    var p = path.getPointAtLength((1-t) * l);
    

    这里是演示:

    //The data for our line
     var lineData = [ 
     	{ "x": 1,   "y": 5},  { "x": 20,  "y": 20},
       { "x": 40,  "y": 10}, { "x": 60,  "y": 40},
       { "x": 80,  "y": 5},  { "x": 100, "y": 60}];
    
    var lineFunction = d3.line()
         .x(function(d) { return d.x; })
         .y(function(d) { return d.y; })
         .curve(d3.curveCardinal);
    
    //The SVG Container
    var svgContainer = d3.select("body").append("svg")
    		.attr("width", 200)
    		.attr("height", 200);
    
    //The line SVG Path we draw
    var lineGraph = svgContainer.append("path")
         .attr("d", lineFunction(lineData))
         .attr("stroke", "blue")
         .attr("stroke-width", 2)              
         .attr("fill", "none");
    
    var circle = svgContainer.append("circle")
        .attr("r", 5)
        .attr("transform", "translate(" + lineData[0].x + "," + lineData[0].y + ")");
    
    transition();
    
    /*
    svgContainer.on("click", function() {
        transition();
    });*/
    
    function transition() {
      circle.transition()
          .duration(10000)
          .attrTween("transform", translateAlong(lineGraph.node()))
          .on("end", transition2);
    }
    
    function transition2() {
      circle.transition()
          .duration(10000)
          .attrTween("transform", translateAlong2(lineGraph.node()));
    }
    
    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 + ")";
        };
      };
    }
    
    function translateAlong2(path) {
      var l = path.getTotalLength();
      
      return function(d, i, a) {
        return function(t) {
          var p = path.getPointAtLength((1-t) * l);
          return "translate(" + p.x + "," + p.y + ")";
        };
      };
    }
    <script src="https://d3js.org/d3.v4.min.js"></script>

    PS:在 D3 v4 中,它是 .on("end"...,而不是 each("end"...

    PPS:我的解决方案中有很多重复。我会让 DRY 为你做作业。

    【讨论】:

    • 感谢您的回复 Gerardo,非常有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-24
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多