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>
      

Run code


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.

+3


source to share


1 answer


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>
      

Run code




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 ....

+7


source







All Articles