【问题标题】:Can't make paths draw growing slowly with D3无法使用 D3 使路径绘制缓慢增长
【发布时间】:2014-12-02 04:00:35
【问题描述】:

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

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

当我尝试在下面的代码 sn-p 中附加 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);

【问题讨论】:

标签: javascript animation svg d3.js


【解决方案1】:

在 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

【讨论】:

  • 这可能与d3.svg.area有关吗?到目前为止,我一直没有成功
  • 建议:您应该使用path.attr('stroke-dashoffset', function() { return this.getTotalLength(); }) 而不是path.node.getTotalLength() 否则,如果在多个数据点上选择pathtotalLength 将只是您所在的第一个path 的长度绘画。后续paths 的动画会非常奇怪。
  • 整洁的技术。根据我对代码的阅读,不可能使用它从路径上的任意点向两个方向向外增长,对吧?
  • @GeorgeMauer 我认为如果你同时动画stroke-dasharraystroke-dashoffset 是可能的,但我无法从我的脑海中弄清楚。我建议打开一个新问题。
【解决方案2】:

我相信执行此操作的“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(如果您的背景很复杂) ) 越过线条,然后将其过渡到右侧以显示下方的线条。

【讨论】:

  • 这当然看起来像 d3 方式,但如果你放慢动画的速度,路径会被附加,而不是动画(至少在 Chrome 中)。
  • 谢谢,非常感谢!
  • 是的,对矩形进行动画处理以发现线条可能会更好地提高性能。在大多数情况下,简单的剪辑路径也会提供良好的性能,但不清楚它是否比调整路径更好(试试看,实现可能会有所不同)。
  • @Duopixel - 是的,这只是逐个滴答地附加下一段。但是您可以扩展补间函数以添加下一个点作为前一个点的副本,然后使用interpolateObjectinterpolateArray 沿路径段补间(但不适用于其他线插值)。
  • P.S.感谢您提供有关 JSBeautifer 的提示。我现在可以在 transitions_010.html 文件中看到该代码,而且你是对的 - 嵌套的“next”子句的混乱级联。
【解决方案3】:

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

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看到它

【讨论】:

  • 谢谢,非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多