Skip to content

Instantly share code, notes, and snippets.

@jczaplew
Created September 18, 2013 01:51
Adaptive Composite Map Projection example
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>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Adaptive Composite Map Projection (Lite)</title>
<style>
body {
background: #fcfcfa;
height: 500px;
position: relative;
width: 960px;
}
.stroke {
fill: none;
stroke: #000;
stroke-width: 3px;
}
.fill {
fill: #000;
}
.graticule {
fill: none;
stroke: #fff;
stroke-width: .5px;
stroke-opacity: .5;
}
.land {
fill: #fff;
stroke:#777;
stroke-width:.75px;
}
.boundary {
fill: none;
stroke: #fff;
stroke-width: .5px;
}
</style>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/d3.geo.projection.v0.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script type="text/javascript">
function pickProjection(scale, coords) {
if (scale <= 1.5) {
d3.select("#proj").text("Hammer");
currentProj = "hammer";
return d3.geo.hammer()
.coefficient(2)
.precision(0.3)
.scale(scale * 100)
.rotate([coords[0],0]);
} else if (scale <= 2.0) {
d3.select("#proj").text("Modified Hammer");
currentProj = "hammer";
return d3.geo.hammer()
.coefficient(2.0 - (scale-1.5) * 2.0)
.precision(0.3)
.scale(scale * 100)
.rotate([coords[0],0]);
} else if (scale <= 6.0) {
d3.select("#proj").text("Lambert azimuthal");
currentProj = "lambert";
return d3.geo.azimuthalEqualArea()
.scale(scale * 100)
.precision(0.3)
.clipAngle(180 - 1e-3)
.rotate(coords);
} else if (scale <= 12) {
d3.select("#proj").text("Albers");
currentProj = "albers";
coords = (coords[0] == 0) ? [0.01, 0.01] : coords;
return d3.geo.albers()
.rotate([coords[0], 0])
.center([0, -coords[1]])
.parallels([ -coords[1] - scale, -coords[1] + scale])
.scale(scale * 100)
.translate([width / 2, height / 2])
.precision(.1);
} else {
d3.select("#proj").text("Mercator");
return d3.geo.mercator()
.scale(scale * 95)
.translate([width / 2, height / 2])
.rotate([coords[0],0])
.center([0, -coords[1]]);
}
}
var width = 960,
height = 500,
scale = 1,
currentProj;
var rotate = [0,0];
var projection = pickProjection(1, [0,0]);
var path = d3.geo.path()
.projection(projection);
var graticule = d3.geo.graticule();
var m0,
o0;
var zoom = d3.behavior.zoom()
.center([width / 2, height / 2])
.on("zoomstart", function(){
m0 = [d3.event.sourceEvent.pageX, d3.event.sourceEvent.pageY];
if (currentProj == "albers") {
var proj = projection.rotate(),
cent = projection.center();
o0 = [-proj[0], cent[1]];
} else {
var proj = projection.rotate();
o0 = [-proj[0],-proj[1]];
}
d3.event.sourceEvent.stopPropagation();
})
.on("zoom", function() {
if (m0) {
var constant = (scale < 4) ? 4 : scale * 2;
var m1 = [d3.event.sourceEvent.pageX, d3.event.sourceEvent.pageY],
o1 = [o0[0] + (m0[0] - m1[0]) / constant, o0[1] + (m1[1] - m0[1]) / constant];
}
rotate = [-o1[0], -o1[1]];
scale = (d3.event.scale >= 1) ? d3.event.scale : 1;
projection = pickProjection(scale, rotate);
d3.selectAll("path").attr("d", path.projection(projection));
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.call(zoom);
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("countries_1e5.json", function(error, data) {
svg.insert("path", ".graticule")
.datum(topojson.feature(data, data.objects.countries))
.attr("class", "land")
.attr("d", path);
d3.select("body").append("text")
.attr("id", "info");
d3.select("body").append("text")
.attr("id", "proj");
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment