Skip to content

Instantly share code, notes, and snippets.

@veltman
Last active February 3, 2018 19:17
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save veltman/bb75c2aa76c9b36f2c849dbb14435e23 to your computer and use it in GitHub Desktop.
Save veltman/bb75c2aa76c9b36f2c849dbb14435e23 to your computer and use it in GitHub Desktop.
Self-drawing arrow

Animating a path with an arrowhead using stroke-dasharray and interpolation along the path for the arrow positioning. The translate is determined by a point along the length of the path and the rotation is determined by calculating the approximate tangent of the path using two nearby points.

See also: Animating along a path

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<style>
path {
fill: none;
stroke: black;
stroke-width: 2px;
display: none;
}
.arrow {
fill: black;
stroke: none;
}
</style>
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="960" height="500">
<path class="swoop" d="M36.2,268.1C70.2,153.8,108.1,58,140.8,61.2
c63.1,6.1,69,376.4,103.1,376.2c33-0.2,47.6-346.4,83.8-346.9c32.4-0.4,54.9,275.7,85.4,274.6c27.7-1,34.1-230,62.3-230.8
c26.2-0.7,48.4,195.5,70,193.8c19.1-1.4,20.7-162.2,43.8-158.5c13.8,2.2,19.3,29.9,24,40.2c17.2,37.4,55.8,58.7,97,54.6
c13.1-1.3,28.6-6.8,38.9-15c9.4-7.5,15.6-20.4,11.6-31.7c-2.8-7.8-9.8-13.5-17.4-16.9c-9.7-4.4-21.1-5.7-31.2-2
c-16.6,6.1-25.2,26.6-14.8,41.8c10.9,16.1,31,17.1,48,21.7c55,14.6,112,3.9,165.4-12.2"/>
<path class="arrow" d="M-5,0 L-15,15 L15,0 L-15,-15 Z"/>
</svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var swoop = d3.select(".swoop"),
arrow = d3.select(".arrow"),
path = swoop.node(),
totalLength = path.getTotalLength();
draw(true);
function draw(immediate) {
var t = d3.transition()
.duration(4000)
.delay(immediate ? 0 : 1000)
.on("start",function(){
d3.selectAll("path").style("display", "block");
})
.on("end",draw);
arrow.transition(t)
.attrTween("transform",function(){
return function(t){
var pos = t * totalLength;
return "translate(" + pointAtLength(pos) + ") rotate( " + angleAtLength(pos) + ")";
};
});
swoop.transition(t)
.attrTween("stroke-dasharray",function(){
return d3.interpolateString("0," + totalLength,totalLength + "," + totalLength);
});
}
function pointAtLength(l) {
var xy = path.getPointAtLength(l);
return [xy.x, xy.y];
}
// Approximate tangent
function angleAtLength(l) {
var a = pointAtLength(Math.max(l - 0.01,0)), // this could be slightly negative
b = pointAtLength(l + 0.01); // browsers cap at total length
return Math.atan2(b[1] - a[1], b[0] - a[0]) * 180 / Math.PI;
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment