This but with canvas rendering, which is a bit faster/smoother.
Last active
February 3, 2018 19:15
-
-
Save veltman/de68ecd92fbeed9920037b04e3f47c08 to your computer and use it in GitHub Desktop.
Swoopy US tour w/ canvas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<style> | |
#swoop { | |
display: none; | |
} | |
path { | |
fill: none; | |
stroke-linejoin: round; | |
stroke-linecap: round; | |
stroke: #444; | |
stroke-width: 2px; | |
} | |
path:last-of-type { | |
stroke-dasharray: 12,5,1,5; | |
} | |
body { | |
background-color: #e9ddcd; | |
} | |
svg, canvas { | |
position: absolute; | |
} | |
</style> | |
</head> | |
<body> | |
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="960" height="500"> | |
<path id="swoop" d="M834.4,67.7c-2.2,11.7-5.9,23.4-11.9,33.7c-2.6,4.5-6.4,8-10.5,11.1c-2,1.6-4.1,3-6.2,4.6c-1.8,1.4-3.7,2.7-5,4.5 | |
c-2.4,3.4-3.2,8.1-2.3,12.1c0.5,2.3,1.4,4.6,3.9,5.3c1.3,0.4,2.8,0.3,4.2,0.2c4.3-0.4,12.3-3.5,15.5,0.6c1.4,1.7,1.6,4,1.3,6.1 | |
c-0.3,2.4-1.3,4.2-3.1,5.7c-4,3.4-9.2,4.6-14.4,3.8c-2.9-0.4-5.7-1-8.6-1.4c-3-0.5-6-1-8.8-2.2c0,0-2.1-0.3-2.1-0.3 | |
c-8.4,5.2-0.1,13.3,1.5,20.1c0.4,1.5,0.7,3,1,4.5c0.3,1.2,0.6,2.3,0.4,3.5c-0.7,4.4-5.8,8.2-10.2,7.9c-5-0.4-9.8-4.2-13.6,0.8 | |
c-0.3,0.4-0.5,0.6-0.5,1c0,0.3,0.3,0.7,0.4,1c0.3,0.6,0.7,1.2,1.1,1.8c1.9,2.3,4.7,3.3,6.8,5.3c2.6,2.5,2.8,4.9,4.4,7.8 | |
c0.8,1.5,1.3,3.2,1.5,4.8c0.4,4.2-3.1,8.6-7.4,9c-4.9,0.5-8.8-5.2-13.8-6.3c-11.2-2.5-21.4,2-31.8,5.5c-1.4,1-6.1,2.4-8,3.1 | |
c-2,0.8-3.9,2-5.3,3.7c-2.7,3.2-3.6,7.9-2,11.8c1.4,3.7,4.8,6.2,8.5,7.2c2.3,0.6,4.6,0.9,6.9,1.5c1.9,0.5,3.7,1.2,5.5,2.1 | |
c6.6,3.5,10.1,10.7,10.9,17.9c0.6,5.8-0.5,11.6-1.8,17.2c-1.1,5-2.8,9.9-5,14.6c-2.1,4.5-4.7,8.8-7.7,12.9c-1.5,2.1-3.1,4.1-4.7,6 | |
c-1.6,1.9-3.4,3.6-4.9,5.6c-0.7,0.9-1.3,1.9-2.4,2.4c-7.2,8.4-17.3,15.7-20.4,26.8c-1.8,6.4-0.5,13.2,1.5,19.5 | |
c1.8,5.7,6,11.5,6.5,17.5c0.3,3.3-0.5,6.7-2.7,9.3c-6.2,7.2-17.8,2.2-25.4,0.9c-10.6-1.9-20.8-3.9-29-11.5c-3.3-3-5.7-7.1-8.6-10.6 | |
c-2.7-3.2-5.2-6.5-8.4-9.1c-3.5-2.8-7.9-4.6-12.1-5.6c-4.4-1-9-1-13.4,0c-4.6,1.1-9,3.3-13.2,5.4c-4.2,2.1-8.3,4.4-12.4,6.7 | |
c-4.1,2.3-8.2,4.4-12.3,6.6c-3.9,2.2-7.6,4.6-11.7,6.4c-3,1.3-6.6,2.6-9.9,2c-7.7-1.3-8.6-11.4-9.8-17.5c-2-10.3-5.1-20.8-0.7-31 | |
c3.4-7.8,9-14.5,16.1-19.4c7.4-5.1,15.7-9,24.4-11.3c4.4-1.2,8.8-2,13.3-2.4c5-0.5,10-0.9,14.9-1.9c8.6-1.8,16.4-6,23.2-11.5 | |
c7.2-5.7,13.3-12.8,18.6-20.2c5.4-7.5,10.1-15.8,13.5-24.4c3.4-8.7,5.3-17.9,4.8-27.2c-0.5-9.9-3.3-19.5-7-28.6 | |
c-1.8-4.4-3.8-8.7-6.1-12.9c-1.1-2.1-2.4-4.1-3.6-6.1c-5.6-8.9-16-11.5-20.3,0c-3.4,9-2.1,19-2.9,28.4c-0.7,7.5-2.3,15.1-7.8,20.6 | |
c-2.5,2.6-5.5,4.6-9,5.5c-3.3,0.8-6.7,0.8-10,0.1c-3.3-0.7-6.4-2.1-9-4.2c-3-2.5-4.8-5.9-5.9-9.5c-1.4-4.3-1.7-9-1.1-13.5 | |
c0.4-2.5,0.9-5,1.1-7.6c0.2-2.6,0.4-5.2,0.4-7.8c0.1-4.8,0.1-9.6-0.5-14.3c-0.6-4.5-1.7-8.9-3.3-13.2c-2.9-7.8-7.3-15.4-13.1-21.5 | |
c-5-5.4-11.3-9.4-18.5-10.9c-4.3-0.9-9-1.1-13.4-0.7c-4.6,0.4-8.9,1.9-12.8,4.4c-8.8,5.6-11.8,14.6-11.2,24.6 | |
c0.2,3.5,0.4,6.9,0.7,10.4c0.7,11.7,10.9,22.8,15.1,33.7c1.9,4.9,3.5,9.8,4.8,14.8c1.4,5.3,2.6,10.8,3.2,16.3 | |
c0.3,3,0.5,6.2,0.1,9.3l0.2,3.3c-0.4,7-2.3,13.7-5.5,19.9c-3.3,6.4-8,11.8-12.5,17.4c-2.3,2.9-4.7,5.7-7.5,8.2 | |
c-3.1,2.8-6.4,5.3-9.6,8c-6.3,5.3-12.5,10.8-18.5,16.5c-6,5.6-11.7,11.5-17.4,17.5c-4.9,5.2-9.5,10.8-14.7,15.6 | |
c-5.5,5-12,8.6-19.4,10c-7.3,1.4-15.1,0-21.2-4.4c-5.1-3.7-8.5-9.1-10.6-15c-1.3-3.6-2.1-7.4-2.2-11.2c-0.1-4.1,0.3-8.2,1-12.2 | |
c4.3-24.8,21.4-44,31.9-66.3c4.6-9.8,7.9-20.4,10.3-30.9c1.3-5.5,2.2-11,2.7-16.6c0.5-5.6,0.6-11.2,0.6-16.8 | |
c0.1-11.3-0.3-22.7-2.1-33.9c-0.9-5.3-2-10.6-3.5-15.7c-0.7-2.6-1.5-5.1-2.4-7.6c-0.4-1.3-0.9-2.5-1.4-3.8 | |
c-0.1-0.2-0.5-0.8-0.4-1.1l-4.2-8.3c-1.7-2.2-3.3-4.4-5.1-6.6c-3.6-4.6-7.5-9-11.9-12.8c-9.1-7.8-20.5-12.6-32.1-15.2 | |
c-12.6-2.9-25.7-2.8-38.5-1.9c-12.7,0.9-25.2,4.8-36.8,10c-17.3,7.7-33.2,19.3-46.7,32.5c-5.7,5.5-10.8,12.2-11.5,20.4 | |
c-0.4,4.4,1,8.7,4.2,11.8c3.4,3.3,8.2,4.9,12.9,5.2c7.5,0.6,15.1,0.3,22.6,0.6c12.1,0.4,24.6,2,35.5,7.6 | |
c9.6,4.9,17.1,12.7,21.9,22.3c3.1,6.2,5.4,12.8,7,19.5c1.6,7,2.2,14.1,2.4,21.3c0.5,14.8-0.5,29.7-4.3,44.1 | |
c-1.8,6.9-4.4,13.5-7.8,19.8c-3,5.8-6.5,11.4-10.6,16.5c-4.1,5.1-8.7,9.9-14.1,13.6c-5.4,3.7-11.5,6.3-17.8,8.1 | |
c-5.4,1.5-10.7,1.9-16.2,0.8c-5.4-1.1-10.6-3.3-14.9-6.7c-4.7-3.6-8-8.4-8.9-14.4c-0.5-3.4-0.4-6.8-0.3-10.2 | |
c0.2-3.7,0.7-7.4,1.4-11.1c4.1-21.1,16.9-42.7,2.6-63.1c-4.9-7-12.3-11.9-20.2-14.8c-5.2-1.9-10.6-3.2-16.1-3.4 | |
c-6.4-0.2-12.8,0.9-19,2.5c-5.5,1.4-10.8,3.2-15.8,5.8c-5.1,2.6-9.5,6-13.9,9.5c-4.4,3.6-9,6.9-14.4,9c-2.7,1.1-5.6,1.9-8.5,2.1 | |
c-2.8,0.2-5.6-0.3-8.3-1.2c-4.2-1.4-7.9-3.8-10.9-7.1c-2.9-3.2-5-7.1-6.4-11.2c-4.2-11.7-3.7-24.2-1.2-36.2 | |
c1.2-5.8,2.8-11.3,4.9-16.8c0.4-1.2,0.9-2.4,1.3-3.6c3.3-9.5,7.8-17.5,13.4-25.8c8.4-12.5,18.2-23.8,26.1-36.7 | |
c8.5-13.8,15.1-28.4,19.9-43.7"/> | |
</svg> | |
<canvas width="960" height="500"></canvas> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.20/topojson.min.js"></script> | |
<script> | |
var context = document.querySelector("canvas").getContext("2d"), | |
swoop = document.getElementById("swoop"), | |
totalLength = swoop.getTotalLength(), | |
numArrows = 8, | |
group = totalLength / numArrows, | |
duration = 1800, | |
arrowLength = Math.round(group * 0.9), | |
arrowheads = d3.range(numArrows).map(function(d){ return d * group + arrowLength; }), | |
swoopPath = new Path2D(swoop.getAttribute("d")), | |
arrowPath = new Path2D("M10,0 L-3,-8 L-3,8 Z"); | |
context.strokeStyle = context.fillStyle = "#d52621"; | |
context.setLineDash([arrowLength, group - arrowLength]); | |
d3.json("/mbostock/raw/4090846/us.json", function(err, us) { | |
var filtered = { | |
type: "GeometryCollection", | |
geometries: us.objects.states.geometries.filter(function(d) { | |
return d.id !== 2 && d.id !== 15 && d.id < 60; // No AK, HI, PR | |
}) | |
}; | |
var inner = topojson.mesh(us, filtered, function(a, b){ return a !== b; }), | |
outer = topojson.mesh(us, filtered, function(a, b){ return a === b; }); | |
var geoPath = d3.geoPath().projection(d3.geoAlbersUsa().fitExtent([[10, 10],[950, 490]], outer)); | |
d3.select("svg").selectAll(".us") | |
.data([outer, inner]) | |
.enter() | |
.append("path") | |
.attr("class", "us") | |
.attr("d", geoPath); | |
d3.timer(update); | |
}); | |
function update(t) { | |
context.setTransform(1, 0, 0, 1, 0, 0); | |
context.clearRect(0, 0, 960, 500); | |
var offset = -group * (t % duration) / duration; | |
context.lineWidth = 5; | |
context.beginPath(); | |
context.lineDashOffset = offset; | |
context.stroke(swoopPath); | |
arrowheads.forEach(function(d){ | |
var l = d - offset; | |
if (l < 0) { | |
l = totalLength + l; | |
} else if (l > totalLength) { | |
l -= totalLength; | |
} | |
var p = pointAtLength(l); | |
context.setTransform(1, 0, 0, 1, p[0], p[1]); | |
context.rotate(angleAtLength(l)); | |
context.beginPath(); | |
context.fill(arrowPath); | |
}); | |
} | |
function pointAtLength(l) { | |
var xy = swoop.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]); | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment