D3不能让路径慢慢增长

时间:2012-11-13 00:04:13

标签: javascript animation svg d3.js

使用d3图形库,我似乎无法让路径慢慢绘制,因此可以看到它们正在增长。

This site在“折线图(展开)”部分中有一个完美的示例,但没有为该部分提供代码。有人可以帮我解决可能导致这种情况发生的D3代码吗?

当我尝试在下面的代码片段中附加delay()或duration()时,路径仍会立即绘制,并且此段之后的所有SVG代码都无法呈现。

    var mpath = svg.append ('path');
        mpath.attr ('d', 'M35 48 L22 48 L22 35 L22 22 L35 22 L35 35 L48 35 L48 48')
             .attr ('fill', 'none')
             .attr ('stroke', 'blue')
             .duration (1000);

3 个答案:

答案 0 :(得分:47)

在svg中为线条设置动画时的常见模式是设置路径长度的stroke-dasharray,然后为stroke-dashoffset设置动画:

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

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

您可以在此处查看演示: http://bl.ocks.org/4063326

答案 1 :(得分:17)

我相信“D3方式”是使用自定义补间功能。您可以在此处查看有效的实施:http://jsfiddle.net/nrabinowitz/XytnD/

这假设您有一个名为line的生成器设置为d3.svg.line来计算路径:

// add element and transition in
var path = svg.append('path')
    .attr('class', 'line')
    .attr('d', line(data[0]))
  .transition()
    .duration(1000)
    .attrTween('d', pathTween);

function pathTween() {
    var interpolate = d3.scale.quantile()
            .domain([0,1])
            .range(d3.range(1, data.length + 1));
    return function(t) {
        return line(data.slice(0, interpolate(t)));
    };
}​

这里的pathTween函数返回一个插值器,它取一条线的给定切片,由我们通过转换的距离定义,并相应地更新路径。

值得注意的是,我怀疑你会通过简单的路线获得更好的表现和更流畅的动画:放一个白色矩形(如果你的背景很简单)或clipPath(如果你的背景在线上是复杂的,并将其转移到右边以显示下面的线。

答案 2 :(得分:1)

根据您链接的帖子,我想出了以下示例:

var i = 0,
    svg = d3.select("#main");

String.prototype.repeat = function(times) {
   return (new Array(times + 1)).join(this);
}

segments = [{x:35, y: 48}, {x: 22, y: 48}, {x: 22, y: 35}, {x: 34, y:35}, {x: 34, y:60}];
line = "M"+segments[0].x + " " + segments[0].y

new_line = line + (" L" + segments[0].x + " " + segments[0].y).repeat(segments.length);
 var mpath = svg.append ('path').attr ('d',new_line )
             .attr ('fill', 'none')
             .attr ('stroke', 'blue')

for (i=0; i<segments.length; i++)
    {
    new_segment = " " + "L"+segments[i].x + " " + segments[i].y
    new_line = line + new_segment.repeat(segments.length-i)
    mpath.transition().attr('d',new_line).duration(1000).delay(i*1000);
    line = line + new_segment

    }

有点难看,但有效。您可以在jsFiddle

上看到它