假设我有一个用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')Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
我想要慢慢绘制出来的路径.我知道如何从头到尾完成它,但在我的情况下,我想从线上的任意点开始,并在两个方向以相同的速率向外绘制.我无法弄清楚如何做到这一点.
我可以利用attrTween并获取随时间变化的数组切片,但如果我这样做,则行移位,因为我不知道如何在每一步正确设置水平偏移.
希望你正在使用链接到的页面上的第二个答案(@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);Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
首先,考虑从开始到结束动画绘制路径的原始常见场景.如果l是路径(由获得的长度path.node().getTotalLength()),那么设定路径的stroke-dasharray到l + ' ' + l使仪表板和它和下一个划线都等于之间的间隙l.在这些条件下,路径看起来是实心的,因为短划线长度l"推动"超过路径末端的间隙.通过设置stroke-dashoffset为l,上面的场景是相反的 - 路径完全是一个间隙(因此是不可见的),并且破折号从路径上掉下来.通过在这两个状态之间转换(从一个偏移到一个没有偏移),我们逐渐绘制一条线.
现在,为了从中间动画,短划线定义为长度0,间隙具有长度l.所以现在由于0长短划线和l长度间隙,线也完全不可见.设置stroke-dashoffset到l/2半路移动这个0长冲下的路径.这是动画的开始状态.最终状态是反向dasharray,其中间隙为0且破折号为l,这使得该线完全固定.要在这些状态之间正确转换,我们还需要将结束状态设置stroke-dashoffset为l.这是我通过实验得出的结果,我不确定如何用文字解释它.但它有效....