Skip to content

Instantly share code, notes, and snippets.

@Fil
Last active January 1, 2020 16:18
Show Gist options
  • Save Fil/63366253a5d2f00640c15b096c29a38c to your computer and use it in GitHub Desktop.
Save Fil/63366253a5d2f00640c15b096c29a38c to your computer and use it in GitHub Desktop.
Eclipses paths
license: mit
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/combine/npm/d3@5,npm/topojson"></script>
<!--
<script src="https://unpkg.com/d3@4.11.0/build/d3.min.js"></script>
<script src="https://unpkg.com/topojson@3.0.2/dist/topojson.min.js"></script>
-->
<style>
body {margin:0;}
svg {
cursor: move; /* fallback if grab cursor is unsupported */
cursor: grab;
cursor: -moz-grab;
cursor: -webkit-grab;
}
svg.dragging {
cursor: grabbing;
cursor: -moz-grabbing;
cursor: -webkit-grabbing;
}
#sphere {
fill: #eff;
}
textPath {
font-weight: bold;
font-family: sans-serif;
font-size: large;
}
</style>
</head>
<body>
<script>
const margin = 5;
const svg = d3.select("body").append("svg");
const sphere = svg
.append("path")
.attr("id", "sphere")
.datum({ type: "Sphere" });
const land = svg.append("path");
const eclipsesg = svg.append("g").classed("eclipses", true);
const label = svg
.append("text")
.attr("dy", -2)
.append("textPath")
.style("text-anchor", "middle");
const projection = d3
.geoOrthographic() // .geoGnomonic().clipAngle(70)
.rotate([-80, -35]);
const path = d3.geoPath().projection(projection);
const color = d3.scaleOrdinal(d3.schemeCategory10);
function draw() {
const width = Math.min(960, window.innerWidth),
height = Math.min(800, window.innerHeight);
projection.fitExtent([[margin, margin], [width - margin, height - margin]], {
type: "Sphere"
});
svg.attr("width", width).attr("height", height);
svg.selectAll("path")
.attr("d", path);
eclipsesg.selectAll('path').style('fill-opacity', 0.6);
const tp = d3.select(label.attr("xlink:href"));
if (!tp.size()) return;
// find which way is up
tp.attr('d', path).style('fill-opacity', 1);
const l = tp.node().getTotalLength(),
up = tp.node().getPointAtLength(0.26 * l).x > tp.node().getPointAtLength(0.24 * l).x;
label
.attr("startOffset", up ? "25%" : "75%")
.text(d => (l > 360 ? d : l > 180 ? d.substring(0, 4) : ""));
}
// "https://unpkg.com/world-atlas/world/110m.json"
d3.json("https://cdn.jsdelivr.net/npm/world-atlas/world/110m.json").then(world => {
land.datum(topojson.feature(world, world.objects.land))
.attr('opacity', 0.01)
.transition()
.duration(2000)
.attr('opacity', 1);
draw();
});
d3.json("eclipses.json").then(eclipses => {
eclipses = topojson.feature(eclipses, eclipses.objects.eclipses);
eclipsesg
.selectAll("path")
.data(eclipses.features)
.enter()
.append("path")
.style("fill", (d, i) => color(i))
.attr("id", (d, i) => "d" + i)
.on("mouseover click", function(d, i) {
label
.attr("xlink:href", "#d" + i)
.datum(d.properties.Date)
.style("fill", color(i));
});
draw();
});
draw();
</script>
<!-- d3.inertia starts here -->
<script src="https://cdn.jsdelivr.net/combine/npm/versor,npm/d3-inertia"></script>
<!--
<script src="https://unpkg.com/versor@0.1/build/versor.min.js"></script>
<script src="https://unpkg.com/d3-inertia@0.1/build/d3-inertia.min.js"></script>
-->
<script>
var inertia = d3.geoInertiaDrag(svg, draw, projection);
d3.timer(function(e) {
if (inertia.timer) return;
var rotate = projection.rotate();
projection.rotate([rotate[0] + 0.12, rotate[1], rotate[2]]);
draw();
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment