从中间逐渐画出一条小路

时间:2014-11-08 04:52:01

标签: svg d3.js

假设我有一个用d3绘制的任意路径



var points = [0, 4, 4, 4, 8, 8, 4, 4, 4, 8, 4, 4, 4, 4, 0];
var svg = d3.select('svg');

var line = d3.svg.line()
            .y(function(d) { return 10*d})
            .x(function(d, t) { return t*20 })
            .interpolate('cubic');

svg.append('path')
  .attr('d', line(points))
  .attr('stroke', 'black')
  .attr('stroke-width', 2)
  .attr('fill', 'none')

<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script>
<svg style="width: 100%; height: 100%; outline: 1px solid green;"></svg>
&#13;
&#13;
&#13;

我想要慢慢画出路径的动画。 I understand how to do it from beginning to end但在我的情况下,我想从线上的任意点开始,向两个方向以相同的速率向外绘制。 我无法弄清楚如何做到这一点。

我可以利用attrTween并且随着时间的推移采取数组的切片,但是如果我这样做,则线移位,因为我不知道如何在每一步都正确设置水平偏移。 / p>

1 个答案:

答案 0 :(得分:7)

希望您正在使用the page you linked to上的第二个答案(@duopixel的答案),因为这是一个更好的方法。如果是这样,那么如果稍微修改属性,则可以从中间开始绘制线:

var points = [0, 4, 4, 4, 8, 8, 4, 4, 4, 8, 4, 4, 4, 4, 0];
var svg = d3.select('svg');

var line = d3.svg.line()
            .y(function(d) { return 10*d})
            .x(function(d, t) { return t*20 })
            .interpolate('cubic');

var path = svg.append('path')
  .attr('d', line(points))
  .attr('stroke', 'black')
  .attr('stroke-width', 2)
  .attr('fill', 'none');

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

path
 .attr("stroke-dasharray", '0 ' + totalLength)
 .attr("stroke-dashoffset", totalLength/2)
 .transition()
   .duration(2000)
   .attr("stroke-dasharray", totalLength + ' 0')
   .attr("stroke-dashoffset", totalLength);
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script>
<svg style="width: 100%; height: 100%; outline: 1px solid green;"></svg>

工作原理:

首先,考虑从开始到结束动画绘制路径的原始常见场景。如果l是路径的长度(由path.node().getTotalLength()获得),则将路径的stroke-dasharray设置为l + ' ' + l会使破折号与其与下一个破折号之间的差距相等到l。在这些条件下,路径看起来是实心的,因为短划线长度为l“推动”超过路径末端的间隙。通过将stroke-dashoffset设置为l,上述情况可以逆转 - 路径完全是间隙(因此不可见),并且破折号从路径上掉下来。通过在这两个状态之间转换(从一个偏移到一个没有偏移),我们逐渐绘制一条线。

现在,要从中间设置动画,短划线的长度为0,间距的长度为l。因此,由于0长短划线和l长度间隙,现在该线也完全不可见。将stroke-dashoffset设置为l/2会将此0长度的短划线移动到路径的中间位置。这是动画的开始状态。结束状态是反向dasharray,其中gap为0,dash-length为l,这使得该行完全可靠。要在这些状态之间正确转换,我们还需要将结束状态的stroke-dashoffset设置为l。这是我通过实验得出的结果,我不确定如何用文字解释它。但它有效......