Draw a path gradually from the middle
Suppose I have an arbitrary path drawn with 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>
I want to animate a path pulling out slowly. I understand how to do this from start to finish , but in my case, I want to start at an arbitrary point on the line and pull outward at the same speed in both directions. I cannot figure out how to do this.
I can use attrTween
and accept time slices of the array, but if I do that, the line is shifted, since I don't know how to properly set the horizontal offset at each step.
source to share
Hopefully you will work with the second answer on the page you linked to (the one by @duopixel) because it is much better. If so, then you can draw the line from the middle if you change the attributes slightly:
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>
How it works:
First, let's look at the original, generic scenario for animating a path drawing from start to finish. If l
is the path length (obtained path.node().getTotalLength()
), then setting the path stroke-dasharray
to l + ' ' + l
makes the dash and the gap between it and the next dash equal l
. Under these conditions, the path will appear to be solid, since the stroke length l
pushes the space past the end of the path. By setting stroke-dashoffset
in l
, the above scenario is reversed - the path is completely clearance (hence invisible) and the dash falls out of the way. Moving between these two states (from one with offset to one without offset), we get a gradual line drawing.
Now, to animate the middle, the dash is defined by the length 0
and the space is the length l
. So now the line is also completely invisible due to the dash with a length of 0 and a gap l
. Setting stroke-dashoffset
to l/2
moves this 0-length mark in the middle of the path. This is the start state of the animation. The final state is the opposite dasharray
, where the gap is 0 and the dash is l
full, making the line completely solid. In order to properly transition between these states, we also need to set the final state stroke-dashoffset
to l
. This was what I calculated experimentally and I'm not sure exactly how to explain it in words. But it works ....
source to share