Can't make paths draw growing slowly with D3

前端 未结 3 1353
谎友^
谎友^ 2020-12-02 14:07

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

This site has a perfect example in the \"Line Chart (Unrolling)

相关标签:
3条回答
  • 2020-12-02 14:26

    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/

    This assumes that you have a generator called line set up with d3.svg.line to calculate the path:

    // 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 pathTween function 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.

    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.

    0 讨论(0)
  • 2020-12-02 14:26

    A common pattern when animating lines in svg is setting a stroke-dasharray of the length of the path and then animate 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

    0 讨论(0)
  • 2020-12-02 14:30

    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

    0 讨论(0)
提交回复
热议问题