Experimenting with d3.geoCircle to create animated circles on an orthographic projection.
This animation needs to be tweened because d3.transition doesn't really work with geoCircle.
license: mit |
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://d3js.org/topojson.v2.min.js"></script> | |
<style> | |
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } | |
.ocean { | |
fill: #dadada; | |
} | |
.geoCircle { | |
fill: red; | |
fill-opacity: 0.5; | |
stroke: red; | |
stroke-width: 2px; | |
} | |
</style> | |
</head> | |
<body> | |
<script> | |
const margin = {top: 50, right: 0, bottom: 50, left: 0}; | |
const width = 960 - margin.left - margin.right, | |
height = 500 - margin.top - margin.bottom; | |
var svg = d3.select("body").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
const config = { | |
radius: 90 * 0.5, | |
center: [0.1278, 51.5074] | |
} | |
d3.json("https://unpkg.com/[email protected]/world/110m.json", (error, world) => { | |
var land = topojson.feature(world, world.objects.land); | |
var projection = d3.geoOrthographic() | |
.fitSize([width, height], land) | |
.clipAngle(90) | |
.precision(0); | |
var path = d3.geoPath() | |
.projection(projection); | |
var geoCircle = d3.geoCircle(); | |
var ocean = svg.append("circle") | |
.attr("class", "ocean") | |
.attr("cx", width / 2) | |
.attr("cy", height / 2) | |
.attr("r", height / 2); | |
var earth = svg.append("path") | |
.datum(land) | |
.attr("d", path); | |
var circle = svg.append("path") | |
.datum({endAngle: 0}) | |
.attr("class", "geoCircle") | |
.attr("d", d => path(geoCircle.center(config.center).radius(d.endAngle)())); | |
circle.transition() | |
.delay(1000) | |
.duration(4000) | |
.ease(d3.easeLinear) | |
.attrTween("d", geoCircleTween(config.radius)); | |
function geoCircleTween(newAngle) { | |
return function(d) { | |
var interpolate = d3.interpolate(d.endAngle, newAngle); | |
return function(t) { | |
d.endAngle = interpolate(t); | |
return path(geoCircle.center(config.center).radius(d.endAngle)()); | |
}; | |
}; | |
} | |
}); | |
</script> | |
</body> |