A remake of a previous block, Dynamic Globe Rotation, but with Fil's d3-inertia module.
TODO:
forked from HarryStevens's block: Dynamic Globe Rotation with Inertia
xxxxxxxxxx
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
margin: 0;
}
#rotation {
position: absolute;
font-family: monospace;
padding: 10px;
background: rgba(255, 255, 255, .5);
}
#rotation input {
width: 300px;
}
line {
stroke: tomato;
stroke-width: 3px;
}
</style>
</head>
<body>
<div id="rotation"></div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/topojson@3.0.2/dist/topojson.js"></script>
<script src="https://unpkg.com/versor@0.0.3/build/versor.min.js"></script>
<script src="https://unpkg.com/d3-inertia@0.0.5/build/d3-inertia.min.js"></script>
<script>
var angles = ["λ", "φ", "γ"];
angles.forEach(function(angle, index){
d3.select("#rotation").append("div")
.attr("class", "angle-label angle-label-" + index)
.html(angle + ": <span>0</span>")
d3.select("#rotation").append("input")
.attr("type", "range")
.attr("class", "angle angle-" + index)
.attr("min", "-180")
.attr("max", "180")
.attr("value", "0");
});
var width = window.innerWidth, height = window.innerHeight;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var projection = d3.geoOrthographic()
.scale(d3.min([width / 2, height / 2]))
.translate([width / 2, height / 2])
.precision(1);
var path = d3.geoPath()
.projection(projection);
var graticule = svg.append("path")
.datum(d3.geoGraticule().step([10, 10]))
.attr("class", "graticule")
.attr("d", path)
.style("fill", "none")
.style("stroke", "#ccc");
var v0, // Mouse position in Cartesian coordinates at start of drag gesture.
r0, // Projection rotation as Euler angles at start.
q0; // Projection rotation as versor at start.
var line = svg.append("line"),
a,
b;
// inertia versor dragging
var inertia = d3.geoInertiaDrag(svg, render, projection);
function render(){
// the red line
a = [inertia.position[0] + inertia.velocity[0] / 10, inertia.position[1] + inertia.velocity[1] / 10],
b = [inertia.position[0] + inertia.velocity[0] * inertia.t / 10, inertia.position[1] + inertia.velocity[1] * inertia.t / 10]
if (inertia.t){
line
.attr("x1", a[0])
.attr("y1", a[1])
.attr("x2", b[0])
.attr("y2", b[1]);
}
update(projection.rotate());
}
function update(eulerAngles){
angles.forEach(function(angle, index){
d3.select(".angle-label-" + index + " span").html(Math.round(eulerAngles[index]))
d3.select(".angle-" + index).property("value", eulerAngles[index])
});
projection.rotate(eulerAngles);
svg.selectAll("path").attr("d", path);
}
d3.selectAll("input").on("input", function(){
var p = [];
d3.selectAll("input").each(function(d, i){
p.push(+d3.select(this).property("value"));
});
update(p);
if (inertia.timer) inertia.timer.stop();
});
d3.json("countries.json", function(error, world){
if (error) throw error;
svg.selectAll(".subunit")
.data(topojson.feature(world, world.objects.polygons).features)
.enter().append("path")
.attr("d", path)
.style("stroke", "#fff")
});
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js
https://unpkg.com/topojson@3.0.2/dist/topojson.js
https://unpkg.com/versor@0.0.3/build/versor.min.js
https://unpkg.com/d3-inertia@0.0.5/build/d3-inertia.min.js