javascript 无法使用 D3 使路径绘制缓慢增长

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13353665/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 18:32:05  来源:igfitidea点击:

Can't make paths draw growing slowly with D3

javascriptanimationsvgd3.js

提问by tgoneil

Using the d3 graphics library, I can't seem to make paths draw slowly so they can be seen growing.

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

This sitehas a perfect example in the "Line Chart (Unrolling)" section, but no code is given for that section. Could someone please help me with the lines of D3 code that could make that happen?

这个网站在“折线图(展开)”部分有一个完美的例子,但没有给出该部分的代码。有人可以帮我解决可以实现这一点的 D3 代码行吗?

When I try appending delay() or duration() such as in the following code snippet, the path still draws immediately, And all the SVG code after this segment fails to render.

当我尝试在下面的代码片段中添加 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);

回答by methodofaction

A common pattern when animating lines in svg is setting a stroke-dasharrayof the length of the path and then animate stroke-dashoffset:

在 svg 中为线条设置动画时的常见模式是设置stroke-dasharray路径长度的a ,然后设置动画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);

You can see a demo here: http://bl.ocks.org/4063326

你可以在这里看到一个演示:http: //bl.ocks.org/4063326

回答by nrabinowitz

I believe the "D3 way" to do this is with a custom tween function. You can see a working implementation here: http://jsfiddle.net/nrabinowitz/XytnD/

我相信执行此操作的“D3 方式”是使用自定义补间函数。你可以在这里看到一个有效的实现:http: //jsfiddle.net/nrabinowitz/XytnD/

This assumes that you have a generator called lineset up with d3.svg.lineto calculate the path:

这是假设你有一个名为发电机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)));
    };
}?

The pathTweenfunction here returns an interpolator that takes a given slice of the line, defined by how far we are through the transition, and updates the path accordingly.

pathTween此处的函数返回一个插值器,该插值器采用给定的线段,由我们通过过渡的距离定义,并相应地更新路径。

It's worth noting, though, that I suspect you'd get better performance and a smoother animation by taking the easy route: put a white rectangle (if your background is simple) or a clipPath(if your background is complex) over the line, and transition it over to the right to reveal the line underneath.

不过,值得注意的是,我怀疑您可以通过简单的方法获得更好的性能和更流畅的动画:clipPath在线条上放置一个白色矩形(如果您的背景很简单)或一个(如果您的背景很复杂),然后将其向右过渡以显示下方的线条。

回答by btel

Based on the post that you link to, I came up with the following example:

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

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

    }

It is a bit ugly, but works. You can see it on jsFiddle

这有点难看,但有效。你可以在jsFiddle看到