Reputation: 1079
I have several geojson layers and I am layering on top of one another using groups. I am centering the map on a given geojson file using Mike's answer found here -> Center a map in d3 given a geoJSON object
My problem, and I believe that it has to do with the asynchronous nature of JavaScript, is that if I put the projection definition on a geojson that is quite large the other geojson features don't project correctly.
How can I properly translate and scale the map using this system? Is there a better way to go about this?
I have found a quick and dirty way to do this but it won't allow me to change the projection programmatically. I have used the debugger to get the values of s and t, then I have to hard code those values at the beginning of the script after the projection is defined, before and geojson functions are called.
Here is my code:
var width = 1100,
height = 850;
var projection = d3.geo.mercator();
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var landGroup = svg.append("g"),
waterGroup = svg.append("g"),
urbanGroup = svg.append("g"),
borderGroup = svg.append("g");
d3.json("geoData/naLand.geojson", function(land) {
projection
.scale(1)
.translate([0,0]);
var b = path.bounds(land),
s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];
projection
.scale(s)
.translate(t);
landGroup.selectAll("path")
.data(land.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "#888888")
.attr("stroke", "#111111")
})
d3.json("geoData/naWater.geojson", function(water) {
waterGroup.selectAll("path")
.data(water.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "#C9DBFF")
.attr("stroke", "#0066FF")
})
d3.json("geoData/PNW_Municipalities.geojson", function(urban) {
urbanGroup.selectAll("path")
.data(urban.features)
.append("path")
.attr("d", path)
.attr("fill", "#666666")
.attr("stroke", "#666666")
})
d3.json("geoData/CanadianBorder.geojson", function(border) {
borderGroup.selectAll("path")
.data(border.features)
.enter()
.append("path")
.attr("d", path)
.attr("stroke", "#555555")
.attr("stroke-width", "3")
.attr("stroke-dasharray", "2,2")
.attr("fill", "transparent")
})
Upvotes: 0
Views: 424
Reputation: 32327
You can use queue.js to club all json loading and when all the json is loaded do the necessary action of drawing the projection.
Something like below:
queue()
.defer(d3.json, 'geoData/naLand.geojson')//this will load the json for land
.defer(d3.json, 'geoData/PNW_Municipalities.geojson')//muncipality
.defer(d3.json, 'geoData/CanadianBorder.geojson')//canadaborder
.await(makeMyMap);
function makeMyMap(error, land, muncipality,canadaborder) {
//make your map
}
Working example here
Hope this helps!
Upvotes: 1