Skip to content

Instantly share code, notes, and snippets.

@mpmckenna8
Last active August 29, 2015 14:04
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 mpmckenna8/7faae8a06dd746c7ca5d to your computer and use it in GitHub Desktop.
Save mpmckenna8/7faae8a06dd746c7ca5d to your computer and use it in GitHub Desktop.
Reproject d3-carto-map three modes including gnomonic

Trying to make a little page to reproject data using d3.carto jam and it kind of works.

This defaults to a gnomonic projection w/ map.mode('globe') which makes for some rotating cool rotation effects when panning the map rather than just transitioning every path like in projection mode.

Then there's the boring old transform mode which I think is just mercator.

Please see d3-cart-map readme.md for a little explanation of the map modes (from which 'globe' is missing). And show me how to use them correctly.

https://github.com/emeeks/d3-carto-map

Things which could make this a little nicer:

-Adding some graticules maybe not to the feature group.

-Adding different kinds of layers.

-Figure out what the errors are about the paths which get multiplied when panning in globe mode.

For some much cleaner better javascript examples of how to do similar things w/ d3 please see Jason Davies stuff like http://www.jasondavies.com/maps/transition/ and Mike Bostocks stuff like http://bl.ocks.org/mbostock/3711652.

Really I'm just trying to figure out how to kind of do some things they did w/ d3-carto-map.

As always let me know if there is anything silly in my code or how I could make it better.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>reprojection selection</title>
<meta charset="utf-8" />
<link type="text/css" rel="stylesheet" href="https://raw.githubusercontent.com/emeeks/d3-carto-map/master/d3map.css" />
<link type="text/css" rel="stylesheet" href="https://raw.githubusercontent.com/emeeks/d3-carto-map/master/examples/example.css" />
</head>
<style>
html,body {
height: 100%;
width: 100%;
margin: 0;
}
#map {
height: 90%;
width: 90%;
top: 10%;
position: absolute;
}
#title {
padding: 20px;
}
.bluesquare {
fill: green;
stroke: gray;
stroke-width: 1px;
}
button.marker {
position: fixed;
z-index: 1;
bottom: 150px;
left: 150px;
}
.countryborders{
fill:#99d8c9;
stroke:#de2d26;
}
.reproject{
margin-top:-15;
}
.reprojectshp{
margin-top:-15;
}
.addgr{
margin-top:-15;
}
#projection-menu{
margin-top:5px;
}
.grat{
stroke:grey;
stroke-width:1px;
stroke-opacity:.7;
fill:none;
}
</style>
<select id="projection-menu"></select>
<script src="./projmode.js" type="text/javascript">
</script>
<body onload="makeSomeMaps()">
<body onload="makeSomeMaps()">
<div id="map"></div>
<footer>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8" type="text/javascript"></script>
<script src="http://d3js.org/topojson.v1.min.js" type="text/javascript">
</script>
<script src="http://d3js.org/d3.geo.projection.v0.min.js" type="text/javascript">
</script>
<script src="/mpmckenna8/raw/55557f2cc06ae603f242/tile.js" type="text/javascript">
</script>
<script src="/mpmckenna8/raw/55557f2cc06ae603f242/d3.quadtiles.js" type="text/javascript">
</script>
<script src="/mpmckenna8/raw/55557f2cc06ae603f242/d3.geo.raster.js" type="text/javascript">
</script>
<script src="https://rawgit.com/emeeks/d3-carto-map/master/d3.carto.map.js" type="text/javascript">
</script>
</footer>
</body>
</html>
function makeSomeMaps() {
var map = d3.carto.map();
d3.select('#map')
.call(map);
map.mode('globe');
var projection = d3.geo.gnomonic()
.clipAngle(90 - 1e-3)
.scale(150)
.translate(map.zoom().translate())
.precision(.1);
map.projection(projection);
// adding the geojon country layer
countryLayer = d3.carto.layer.geojson();
countryLayer
.path("/mpmckenna8/raw/f6245adc7a3cd3930a11/world.geojson")
.label("Countries")
.cssClass("countryborders")
.renderMode("svg")
.on('load', drawgrat);
map.addCartoLayer(countryLayer);
// var mapsvg =;
d3.select("#map").append("button").attr("class", "reproject").html("projection mode").on("click", reproject);
d3.select("#map").append("button").attr("class", "reprojectshp").html("Globe mode").on("click", sphereit);
d3.select("#map").append("button").attr("class", "addGr").html("Transform mode").on("click", tranmo);
function reproject(){
var projection = d3.geo.conicEquidistant()
.center([0, 0])
.scale(3)
.translate(map.zoom().translate())
.precision(.1);
map.projection(projection);
map.mode('projection');
map.refresh();
};
// this is the funciton getting called by the sphere thing
function sphereit(){
map.mode('globe');
map.refresh;
};
// big list of d3.geo projections from http://bl.ocks.org/mbostock/3711652
var options = [
{name: "Select a projection Gnomonic def"},
{name: "Aitoff", projection: d3.geo.aitoff()},
{name: "Albers", projection: d3.geo.albers().scale(145).parallels([20, 50])},
{name: "August", projection: d3.geo.august().scale(60)},
{name: "Baker", projection: d3.geo.baker().scale(100)},
{name: "Boggs", projection: d3.geo.boggs()},
{name: "Bonne", projection: d3.geo.bonne().scale(120)},
{name: "Bromley", projection: d3.geo.bromley()},
{name: "Collignon", projection: d3.geo.collignon().scale(93)},
{name: "Craster Parabolic", projection: d3.geo.craster()},
{name: "Eckert I", projection: d3.geo.eckert1().scale(165)},
{name: "Eckert II", projection: d3.geo.eckert2().scale(165)},
{name: "Eckert III", projection: d3.geo.eckert3().scale(180)},
{name: "Eckert IV", projection: d3.geo.eckert4().scale(180)},
{name: "Eckert V", projection: d3.geo.eckert5().scale(170)},
{name: "Eckert VI", projection: d3.geo.eckert6().scale(170)},
{name: "Eisenlohr", projection: d3.geo.eisenlohr().scale(60)},
{name: "Equirectangular (Plate Carrée)", projection: d3.geo.equirectangular()},
{name: "Hammer", projection: d3.geo.hammer().scale(165)},
{name: "Hill", projection: d3.geo.hill()},
{name: "Goode Homolosine", projection: d3.geo.homolosine()},
{name: "Kavrayskiy VII", projection: d3.geo.kavrayskiy7()},
{name: "Lambert cylindrical equal-area", projection: d3.geo.cylindricalEqualArea()},
{name: "Lagrange", projection: d3.geo.lagrange().scale(120)},
{name: "Larrivée", projection: d3.geo.larrivee().scale(95)},
{name: "Laskowski", projection: d3.geo.laskowski().scale(120)},
{name: "Loximuthal", projection: d3.geo.loximuthal()},
// {name: "Mercator", projection: d3.geo.mercator().scale(490 / 2 / Math.PI)},
{name: "Miller", projection: d3.geo.miller().scale(100)},
{name: "McBryde–Thomas Flat-Polar Parabolic", projection: d3.geo.mtFlatPolarParabolic()},
{name: "McBryde–Thomas Flat-Polar Quartic", projection: d3.geo.mtFlatPolarQuartic()},
{name: "McBryde–Thomas Flat-Polar Sinusoidal", projection: d3.geo.mtFlatPolarSinusoidal()},
{name: "Mollweide", projection: d3.geo.mollweide().scale(165)},
{name: "Natural Earth", projection: d3.geo.naturalEarth()},
{name: "Nell–Hammer", projection: d3.geo.nellHammer()},
{name: "Polyconic", projection: d3.geo.polyconic().scale(100)},
{name: "Robinson", projection: d3.geo.robinson()},
{name: "Sinusoidal", projection: d3.geo.sinusoidal()},
{name: "Sinu-Mollweide", projection: d3.geo.sinuMollweide()},
{name: "van der Grinten", projection: d3.geo.vanDerGrinten().scale(75)},
{name: "van der Grinten IV", projection: d3.geo.vanDerGrinten4().scale(120)},
{name: "Wagner IV", projection: d3.geo.wagner4()},
{name: "Wagner VI", projection: d3.geo.wagner6()},
{name: "Wagner VII", projection: d3.geo.wagner7()},
{name: "Winkel Tripel", projection: d3.geo.winkel3()}
];
var menu = d3.select("#projection-menu")
.on("change", change);
menu.selectAll("option")
.data(options)
.enter().append("option")
.text(function(d) { return d.name; });
function change(){
console.log(options[this.selectedIndex].projection);
var projector = options[this.selectedIndex].projection;
var projection = projector
.center([0, 0])
.scale(100)
// .translate(map.zoom().translate())
.precision(.1);
map.projection(projection);
map.refresh();
}
function drawgrat(){
var g = d3.select('g.features');
var path = d3.geo.path()
.projection(projection);
var graticule = d3.geo.graticule();
g.append('path')
.datum(graticule)
.attr("class", function(d){
console.log(d);
return 'grat'})
.attr('d', path)
.attr('fill', 'none')
.attr('stroke', 0);
map.refresh();
}
// probably the boringest map mode, can't reproject
function tranmo(){
map.mode('transform');
map.refresh;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment