Skip to content

Instantly share code, notes, and snippets.

@yuletide
Forked from alexmacy/.block
Last active April 5, 2022 17:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yuletide/ad105cc7e7f00e532d5a4f7e67c616a4 to your computer and use it in GitHub Desktop.
Save yuletide/ad105cc7e7f00e532d5a4f7e67c616a4 to your computer and use it in GitHub Desktop.
Projection Transitions v4
license: gpl-3.0

A v4 update to mbostock's block: Projection Transitions

I also tweaked the transition so that it's constantly moving...

These projections are available in the geo.projection plugin.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
background: #fcfcfa;
height: 500px;
position: relative;
width: 960px;
}
#projection-menu {
position: absolute;
right: 10px;
top: 10px;
}
.stroke {
fill: none;
stroke: #000;
stroke-width: 3px;
}
.fill {
fill: #fff;
}
.graticule {
fill: none;
stroke: #777;
stroke-width: .5px;
stroke-opacity: .5;
}
.land {
fill: #222;
}
.boundary {
fill: none;
stroke: #fff;
stroke-width: .5px;
}
</style>
<select id="projection-menu"></select>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="//d3js.org/d3-geo-projection.v1.min.js"></script>
<script src="//d3js.org/topojson.v2.min.js"></script>
<script>
var width = 960,
height = 500;
var options = [
{name: "Aitoff", projection: d3.geoAitoff()},
{name: "Albers", projection: d3.geoAlbers().scale(145).parallels([20, 50])},
{name: "August", projection: d3.geoAugust().scale(60)},
{name: "Baker", projection: d3.geoBaker().scale(100)},
{name: "Boggs", projection: d3.geoBoggs()},
{name: "Bonne", projection: d3.geoBonne().scale(120)},
{name: "Bromley", projection: d3.geoBromley()},
{name: "Collignon", projection: d3.geoCollignon().scale(93)},
{name: "Craster Parabolic", projection: d3.geoCraster()},
{name: "Eckert I", projection: d3.geoEckert1().scale(165)},
{name: "Eckert II", projection: d3.geoEckert2().scale(165)},
{name: "Eckert III", projection: d3.geoEckert3().scale(180)},
{name: "Eckert IV", projection: d3.geoEckert4().scale(180)},
{name: "Eckert V", projection: d3.geoEckert5().scale(170)},
{name: "Eckert VI", projection: d3.geoEckert6().scale(170)},
{name: "Eisenlohr", projection: d3.geoEisenlohr().scale(60)},
{name: "Equirectangular (Plate Carrée)", projection: d3.geoEquirectangular()},
{name: "Hammer", projection: d3.geoHammer().scale(165)},
{name: "Hill", projection: d3.geoHill()},
{name: "Goode Homolosine", projection: d3.geoHomolosine()},
{name: "Kavrayskiy VII", projection: d3.geoKavrayskiy7()},
{name: "Lambert cylindrical equal-area", projection: d3.geoCylindricalEqualArea()},
{name: "Lagrange", projection: d3.geoLagrange().scale(120)},
{name: "Larrivée", projection: d3.geoLarrivee().scale(95)},
{name: "Laskowski", projection: d3.geoLaskowski().scale(120)},
{name: "Loximuthal", projection: d3.geoLoximuthal()},
// {name: "Mercator", projection: d3.geoMercator().scale(490 / 2 / Math.PI)},
{name: "Miller", projection: d3.geoMiller().scale(100)},
{name: "McBryde–Thomas Flat-Polar Parabolic", projection: d3.geoMtFlatPolarParabolic()},
{name: "McBryde–Thomas Flat-Polar Quartic", projection: d3.geoMtFlatPolarQuartic()},
{name: "McBryde–Thomas Flat-Polar Sinusoidal", projection: d3.geoMtFlatPolarSinusoidal()},
{name: "Mollweide", projection: d3.geoMollweide().scale(165)},
{name: "Natural Earth", projection: d3.geoNaturalEarth()},
{name: "Nell–Hammer", projection: d3.geoNellHammer()},
{name: "Polyconic", projection: d3.geoPolyconic().scale(100)},
{name: "Robinson", projection: d3.geoRobinson()},
{name: "Sinusoidal", projection: d3.geoSinusoidal()},
{name: "Sinu-Mollweide", projection: d3.geoSinuMollweide()},
{name: "van der Grinten", projection: d3.geoVanDerGrinten().scale(75)},
{name: "van der Grinten IV", projection: d3.geoVanDerGrinten4().scale(120)},
{name: "Wagner IV", projection: d3.geoWagner4()},
{name: "Wagner VI", projection: d3.geoWagner6()},
{name: "Wagner VII", projection: d3.geoWagner7()},
{name: "Winkel Tripel", projection: d3.geoWinkel3()}
];
options.forEach(function(o) {
o.projection.rotate([0, 0]).center([0, 0]);
});
var //interval = setInterval(loop, 750),
i = 0,
n = options.length - 1;
var projection = options[i].projection;
var path = d3.geoPath(projection);
var graticule = d3.geoGraticule();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("defs").append("path")
.datum({type: "Sphere"})
.attr("id", "sphere")
.attr("d", path);
svg.append("use")
.attr("class", "stroke")
.attr("xlink:href", "#sphere");
svg.append("use")
.attr("class", "fill")
.attr("xlink:href", "#sphere");
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
d3.json("world-110m.json", function(error, world) {
if (error) throw error;
svg.insert("path", ".graticule")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
});
var menu = d3.select("#projection-menu")
.on("change", change);
menu.selectAll("option")
.data(options)
.enter().append("option")
.text(function(d) { return d.name; });
//update(options[0])
function loop() {
//var j = Math.floor(Math.random() * n);
//menu.property("selectedIndex", i = j + (j >= i));
//update(options[i]);
}
function change() {
clearInterval(interval);
update(options[this.selectedIndex]);
}
function update(option) {
svg.selectAll("path").interrupt().transition()
.duration(1000).ease(d3.easeLinear)
.attrTween("d", projectionTween(projection, projection = option.projection))
//d3.timeout(loop, 1000)
}
function projectionTween(projection0, projection1) {
return function(d) {
var t = 0;
var projection = d3.geoProjection(project)
.scale(1)
.translate([width / 2, height / 2]);
var path = d3.geoPath(projection);
function project(λ, φ) {
λ *= 180 / Math.PI, φ *= 180 / Math.PI;
var p0 = projection0([λ, φ]), p1 = projection1([λ, φ]);
return [(1 - t) * p0[0] + t * p1[0], (1 - t) * -p0[1] + t * -p1[1]];
}
return function(_) {
t = _;
return path(d);
};
};
}
</script>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment