Skip to content

Instantly share code, notes, and snippets.

@Andrew-Reid
Last active December 26, 2016 20:54
Show Gist options
  • Save Andrew-Reid/b731aba088ed719208f48a09d6aa1225 to your computer and use it in GitHub Desktop.
Save Andrew-Reid/b731aba088ed719208f48a09d6aa1225 to your computer and use it in GitHub Desktop.
Setting an Conic Equal Area Projection

The map above can be modified to change the projection parameters. It is an Conic Equal Area projection. I was having a bit of difficulty at first in producing maps that showed a specific area with d3.js. I've built this to test out different projections. The map will update when any of the text inputs change (which requires defocus - click elsewhere). This is d3.js v4. As always, the topojson file has to be in unprojected coordinates (lat/long).

Any Conic Equal Area projection can be built rather easily in D3.js. The input parameters are:

Rotate(x) and Rotate(y) which refer to the .rotate([x,y])) part of the projection. For most standard projections the y rotation should be zero. This should be the negative of the central meridian of your map. This meridian will be vertical in your projection.

Center(x) and Center(y) which refer to the translation of the map (.center([x,y])). This is where the central latitude should be specified. Specifying a central meridian here is not ideal due to the nature of conical projections, so it should be set as zero.

Parallel(1) and Parallel(2) which refer to the secant lines of the map (.parallels([1,2])), that is the two lines of latitude in which the conical projection intersects the actual globe. On these lines there is no distorition, while near them distorition is minimized. These should be within the geographical feature you want to show or within the important parts of the map. These two can be borrowed from any defined projection, the center and rotation properties will simply transpose or rotate the projection, while distortion is based off of the parallels.

Scale just refers to the zoom level, greater numbers cover smaller geographic extents.

Here are some example parameters:

Australia

projection.rotate([-132,0]).center([0,-28]).parallels([-18,-36]).scale(750);

Mexico

projection.rotate([105,0]).center([0,22]).parallels([14.5,32.5]).scale(1200);

###China projection.rotate([-105,0]).center([0,35]).parallels([27,45]).scale(750);

###Brazil projection.rotate([50,0]).center([0,-15]).parallels([10,-40]).scale(650);

###India projection.rotate([-78,0]).center([0,21.5]).parallels([12,28]).scale(1000);

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
svg {
background: #9ecae1;
}
.legend {
position:fixed;
left: 20px;
top: 30px;
}
.boundary {
fill:none;
stroke: white;
}
.land {
fill: #41ab5d;
}
input {
width: 50px;
position:absolute;
left: 80px;
}
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v1.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
</head>
<body>
<p class="legend">
Rotate (x) <input type="text" class="input" value="50" id="rotateX"> </input> <br />
Rotate (y) <input type="text" class="input" value="0" id="rotateY"> </input> <br />
Center (x) <input type="text" class="input" value="0" id="centerX"> </input> <br />
Center (y) <input type="text" class="input" value="72" id="centerY"> </input> <br />
Parallel (1) <input type="text" class="input" value="60" id="parallel1"> </input> <br />
Parallel (2) <input type="text" class="input" value="80" id="parallel2"> </input> <br />
Scale <input type="text" class="input" value="1100" id="scale"> </input> <br />
</p>
<br />
<script type="text/javascript">
var width = 960,
height = 500;
var rotateX = 50;
var rotateY = 0;
var centerX = 0;
var centerY = 72;
var scale = 1000;
var parallel1 = 60;
var parallel2 = 80;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var projection = d3.geoConicEqualArea()
.rotate([rotateX, rotateY])
.parallels([parallel1, parallel2])
.center([centerX,centerY])
.scale(scale)
.translate([width/2, height/2]);
var path = d3.geoPath().projection(projection);
var g = svg.append("g");
d3.json("world.json", function(error, world) {
g.insert("path", ".land")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
g.insert("path", ".boundary")
.datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
.attr("class", "boundary")
.attr("d", path);
});
d3.select("#rotateX").on("change", function(){
rotateX = this.value; update();
});
d3.select("#rotateY").on("change", function() {
rotateY = this.value; update();
});
d3.select("#centerX").on("change", function(){
centerX = this.value; update();
});
d3.select("#centerY").on("change", function() {
centerY = this.value; update();
});
d3.select("#parallel1").on("change", function(){
parallel1 = this.value; update();
});
d3.select("#parallel2").on("change", function() {
parallel2 = this.value; update();
});
d3.select("#scale").on("change", function() {
scale = this.value; update();
});
function update() {
projection
.rotate([rotateX,rotateY])
.center([centerX,centerY])
.parallels([parallel1,parallel2])
.scale(scale)
;
path = d3.geoPath().projection(projection);
d3.selectAll("path").attr("d", path);
};
</script>
</body>
Display the source blob
Display the rendered blob
Raw
Loading
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