Climatologist Irving I. Gringorten published this little-known equal-area projection in 1972.
It is available as d3.geo.gringorten
in the geo.projection D3 plugin.
Climatologist Irving I. Gringorten published this little-known equal-area projection in 1972.
It is available as d3.geo.gringorten
in the geo.projection D3 plugin.
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
font-family: sans-serif; | |
} | |
.background { | |
fill: #fff; | |
} | |
.foreground { | |
fill: none; | |
stroke: #333; | |
stroke-width: 1.5px; | |
} | |
.graticule { | |
fill: none; | |
stroke: #000; | |
stroke-width: .5px; | |
} | |
.graticule:nth-child(2n) { | |
stroke-dasharray: 2,2; | |
} | |
.land { | |
fill: #eee; | |
stroke: #000; | |
stroke-width: .5px; | |
} | |
.boundary { | |
fill: none; | |
stroke: #999; | |
stroke-width: .5px; | |
} | |
</style> | |
<label for="quincuncial"><input type="checkbox" id="quincuncial" checked> Quincuncial</label> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://d3js.org/d3.geo.projection.v0.min.js"></script> | |
<script> | |
var width = 960, | |
height = 500, | |
initial = [0, 0, 0], | |
velocity = [.005, 0], | |
rotate = initial.slice(), | |
t0 = Date.now(), | |
transitioning = false; | |
var projection = d3.geo.gringorten().translate([width / 2 - .5, height / 2 - .5]).scale(150), | |
path = d3.geo.path().projection(projection); | |
var graticule = d3.geo.graticule().extent([[-180, -80], [180, 80]]), | |
graticuleS = d3.geo.graticule().extent([[-180, -90 + 1e-6], [180, -80 + 1e-6]]).step([90, 10]), // TODO allow negative step size? e.g. -90 to -80, step -10. | |
graticuleN = d3.geo.graticule().extent([[-180, 80], [180, 90]]).step([90, 10]); | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height) | |
.call(d3.behavior.drag() | |
.origin(function() { return {x: rotate[0], y: -rotate[1]}; }) | |
.on("dragstart", function() { transitioning = true; }) | |
.on("drag", function(d) { | |
rotate[0] = d3.event.x; | |
rotate[1] = -d3.event.y; | |
projection.rotate(rotate); | |
svg.selectAll("path").attr("d", path); | |
}) | |
.on("dragend", function() { | |
transitioning = false; | |
t0 = Date.now(); | |
initial = rotate.slice(); | |
})); | |
d3.select("#quincuncial").on("change", change); | |
projection.rotate(initial); | |
svg.append("rect").attr("class", "background"); | |
svg.selectAll(".graticule") | |
.data(graticule.lines().concat(graticuleS.lines()).concat(graticuleN.lines())) | |
.enter().append("path") | |
.attr("class", "graticule"); | |
svg.append("rect").attr("class", "foreground"); | |
change(); | |
function change() { | |
projection.quincuncial(this.checked).rotate([0, 0, 0]); | |
svg.selectAll("path").attr("d", path); | |
var dx = projection([180, 0])[0] - projection([-180, 0])[0], | |
dy = Math.abs(projection([0, -90])[1] - projection([0, 90])[1]); | |
svg.selectAll("rect") | |
.attr("transform", "translate(" + projection([0, 0]) + ")") | |
.attr("x", -dx / 2) | |
.attr("y", -dy / 2) | |
.attr("width", dx) | |
.attr("height", dy); | |
projection.rotate(rotate); | |
} | |
d3.json("/d/3682676/readme-boundaries.json", function(err, collection) { | |
svg.insert("g", ".graticule") | |
.attr("class", "boundary") | |
.selectAll("path") | |
.data(collection.geometries) | |
.enter().append("path") | |
.attr("d", path); | |
}); | |
d3.json("/d/3682676/readme-land.json", function(err, collection) { | |
svg.insert("g", ".graticule,.boundary") | |
.attr("class", "land") | |
.selectAll("path") | |
.data(collection.geometries) | |
.enter().append("path") | |
.attr("d", path); | |
}); | |
d3.timer(function() { | |
if (transitioning) return; | |
var t = Date.now() - t0; | |
rotate[0] = initial[0] + velocity[0] * t; | |
rotate[1] = initial[1] + velocity[1] * t; | |
projection.rotate(rotate); | |
svg.selectAll("path").attr("d", path); | |
}); | |
</script> |