# d3 map rendering sideways

I have a simple d3 map displaying data from Canada in topojson format, but the entire map is rendering sideways. I have been playing with the rotation parameters but I can't seem to get it just right. I'm wondering if anybody else has had this problem because it seems to me like there should be a very simple swap of an x and a y somewhere that would fix this, but I cannot find it since I am rather new to d3.

This is the code:

window.onload = initialize(); //start script once HTML is loaded

function initialize(){ //the first function called once the html is loaded
setMap();
};

//set choropleth map parameters
function setMap(){

//map frame dimensions
var width = 1000;
var height = 750;

//create a new svg element with the above dimensions
var map  = d3.select('body')
.append('svg')
.attr('width', width)
.attr('height', height);

var projection = d3.geo.albers()
.center([-56, 75])
.rotate([0, 0, 0])
.parallels([50, 70])
.scale(750)
.translate([width / 2, height / 2]);

//create svg path generator using the projection
var path = d3.geo.path()
.projection(projection);

queue()
.await(callback); //trigger callback function once data is loaded

function callback(error, ridingData) {

//add electoral boundaries geometry to map
var ridings = map.append('path')
.attr('class', 'ridings')
.attr('d', path)

};
}


And this is the result:

• Try swapping the center coordinates and make the 75 negative: [-75, 56]. At least I assume you didn't want the central meridian in the Indian Ocean. If that's still too far east, try -97 or so. – mkennedy Jun 29 '17 at 19:14
• swap the coordinate order in your input file – Ian Turton Jun 29 '17 at 19:45
• @iant: I don't understand why I would need to do that, because I converted my data to geojson in QGIS, then converted that to topojson using topo2geo (github.com/topojson/topojson-server/blob/master/…). Everything should be in the right standards for it to display – wfgeo Jun 30 '17 at 11:33
• @mkennedy.: My initial coordinates are 56 W, 75 N. This is the approximate geographic centre of Canada. – wfgeo Jun 30 '17 at 11:34
• you need to swap them because some one in your tool chain is expecting lon/lat instead of lat/lon or visaversa – Ian Turton Jun 30 '17 at 13:39

Centering an Albers projection in d3.js can be tricky.

Your map is displaying as it should in d3. This will make more sense if we center on [0,0] and zoom out. A resulting map of the world will look like this:

For reference, the projection I used is in the above map is (I've excluded the scale as this is dependent on svg size):

d3.geo.albers()
.parallels([50,70])
.rotate([0,0,0])
.center([0,0])
.translate([width/2, height/2])


Note: in d3v4 d3.geo.albers() would be d3.geoAlbers()

If we center the map on any coordinate, d3 will only shift the map to the target location. This will result in an image similar to yours. For example, if we centered and zoomed to Canada, we would get an area similar to the boxed area below:

This looks an awful lot like the problem you are describing.

Note, I am using 62.4 N, 96.466667 W as the geographic center of Canada in this answer

The solution to your problem is therefore to rotate the projection along the x axis. Taking the world map from above, if we rotate it 96.4666667 degrees (we rotate the earth under us, so it is the inverse of the longitude we want), we will get:

The projection I am using for the above map:

   var projection = d3.geo.albers()
.parallels([50,70])
.rotate([96.466667,0,0])
.center([0,0])
.translate([width/2, height/2])


Remember that D3 coordinates are always [x,y].

Now we can center to an appropriate y coordinate, in this case I'm using 62.4 N, and zoom in to an appropriate degree (I'll use a 960px x 500px svg for reference):

And the projection:

  var projection = d3.geo.albers()
.parallels([50,70])
.rotate([96.466667,-62.4,62.4])
.center([0,0])
.translate([width/2, height/2])
.scale(700);


Summing that up, the easiest way to create an Albers is to use the following parameters:

d3.geo.albers()
.rotate([-x,0])
.center([0,y])
.parallels([a,b])
.translate([width/2,height/2])
.scale(k);


Where x is your longitude, y is your latitude, a and b your parallels, and k your scale (which dependent on your svg size). You do not need to specify the third rotational value, its default is zero. And, if you don't have two parallels, but wish to use one, you can specify the same value for a and b.

Also, unlike most other projections in d3, the default is not [0,0]. I believe this is because, as an Albers has two secant lines or parallels, having all zero defaults wouldn't be useful. Instead, the default values are for the continental United States. For your projection parameters, you have set the rotation to [0,0,0] to over-ride the default rotation. Not overriding these defaults may lead to unexpected behaviour.