具有不同数据点数的路径之间的转换

时间:2016-03-30 16:01:48

标签: animation d3.js

使用d3我试图在具有不同数据点数的两行之间创建动画。

我引用了Mike Bostock的帖子:https://bl.ocks.org/mbostock/3916621,其中包含以“M0 ...”格式描述的两个路径的pathTween方法。

我想绘制的数据是原始数据点。 例如:

var line = d3.svg.line().interpolate("monotone")
  .x(function(d){ return d.x; })
  .y(function(d){ return d.y; });

low_res = [
    {x: 0     , y: 4  },
    {x: 5     , y: 14 },
    {x: 10  , y: 11 },
    {x: 85  , y: 14 },
    {x: 90  , y: 11 },
    {x: 95  , y: 7  },
    {x: 100 , y: 4  },
  ];
  var high_res = [[
    {x: 0     , y: 4  },
    {x: 1     , y: 12 },
    {x: 2     , y: 11 },
    {x: 3     , y: 11 },
    {x: 4     , y: 14 },
    {x: 5     , y: 14 },
    {x: 6     , y: 12 },
    {x: 7     , y: 4  },
    {x: 8     , y: 3  },
    {x: 9     , y: 1  },
    {x: 10  , y: 11 },
    {x: 11  , y: 11 },
    {x: 12  , y: 1  },
    {x: 13  , y: 13 },
    {x: 14  , y: 1  },
    {x: 15  , y: 5  },
    {x: 16  , y: 13 },
    {x: 17  , y: 10 },
    ]]
  var lines = svg.selectAll(".line").data(high_res)
          .enter()
          .append("path")
          .attr("class","line")
          .attr("d", line)
          .style("stroke", "blue");

这适用于显示high_res图。 Mike Bostock的例子如下:

  var d0 = "M0,0c100,0 0,100 100,100c100,0 0,-100 100,-100",
          d1 = "M0,0c100,0 0,100 100,100c100,0 0,-100 100,-100c100,0 0,100 100,100";
    svg.append("path")
            .attr("transform", "translate(180,150)scale(2,2)")
            .attr("d", d0)
            .call(transition, d0, d1);

    function transition(path, d0, d1) {
        path.transition()
                .duration(2000)
                .attrTween("d", pathTween(d1, 4))
                .each("end", function() { d3.select(this).call(transition, d1, d0); });
    }

    function pathTween(d1, precision) {
        return function() {
            var path0 = this,
                    path1 = path0.cloneNode(),
                    n0 = path0.getTotalLength(),
                    n1 = (path1.setAttribute("d", d1), path1).getTotalLength();

            // Uniform sampling of distance based on specified precision.
            var distances = [0], i = 0, dt = precision / Math.max(n0, n1);
            while ((i += dt) < 1) distances.push(i);
            distances.push(1);

            // Compute point-interpolators at each distance.
            var points = distances.map(function(t) {
                var p0 = path0.getPointAtLength(t * n0),
                        p1 = path1.getPointAtLength(t * n1);
                return d3.interpolate([p0.x, p0.y], [p1.x, p1.y]);
            });

            return function(t) {
                return t < 1 ? "M" + points.map(function(p) { return p(t); }).join("L") : d1;
            };
        };
    }

我正在努力弄清楚如何在我的原始数据集中创建一个本机路径对象,例如d0,d1,它可以传递给转换函数,即:

.call(transition, d0, d1);

非常感谢任何建议。

1 个答案:

答案 0 :(得分:1)

您的问题似乎归结为:

  

如何为数据点生成路径?

这实际上是线功能正在做的事情。它很简单:

&#13;
&#13;
var low_res = [
    {x: 0   , y: 4  },
    {x: 5   , y: 14 },
    {x: 10  , y: 11 },
    {x: 85  , y: 14 },
    {x: 90  , y: 11 },
    {x: 95  , y: 7  },
    {x: 100 , y: 4  },
  ],
  high_res = [
    {x: 0     , y: 4  },
    {x: 1     , y: 12 },
    {x: 2     , y: 11 },
    {x: 3     , y: 11 },
    {x: 4     , y: 14 },
    {x: 5     , y: 14 },
    {x: 6     , y: 12 },
    {x: 7     , y: 4  },
    {x: 8     , y: 3  },
    {x: 9     , y: 1  },
    {x: 10  , y: 11 },
    {x: 11  , y: 11 },
    {x: 12  , y: 1  },
    {x: 13  , y: 13 },
    {x: 14  , y: 1  },
    {x: 15  , y: 5  },
    {x: 16  , y: 13 },
    {x: 17  , y: 10 },
  ];
    
var line = d3.svg.line().interpolate("monotone")
  .x(function(d){ return d.x; })
  .y(function(d){ return d.y; });
    
var d0 = line(low_res),
    d1 = line(high_res);
    
console.log(d0);
console.log(d1);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
&#13;
&#13;