Reputation: 1250
What do I want to do?
I've already made the SVG element the same size as the leaflet layer; and have it as an overlay.
How am I doing it now?
I have some globals that line up with leaflet's values (Map.zoom, Map.width, Map.height, Map.center).
Map.center = [43, -72];
Map.zoom = 3;
Map.projection = d3.geo.mercator()
.center([Map.center[1], Map.center[0]])
// I think this is the problem. I don't really understand this.
.scale(256 * Math.pow(2, Map.zoom))
.translate([Map.width / 2, Map.height / 2])
Map.lt = new L.Map...(center is Map.center, zoom is Map.zoom)
Any time leaflet changes I update the global values and recalculate Map.projection.
I have a function:
function transform(d) {
d = Map.projection(d.value.geometry.coordinates[0], d.value.geometry.coordinates[1]);
return "translate(" + d[0] + "," + d[1] + ")";
}
Then on objects and elements I need to position I call:
object.attr("transform", transform);
My problem is that the layers are not in sync.
When I center my map on [43, -72] and I look at the x,y value returned (from Map.projection) it is exactly in the middle of my SVG layer, so I am guessing there is something wrong with my scale. I am not sure how I can make these values line up correctly.
I don't want to use d3.geo.tile, or d3.geo.path() as I need more flexibility in control over the positioning and animation of my elements.
I just want to know how I can line up leaflets positioning with my SVG layer, only by utilizing d3 functions. I dont wish to rely on leaflet for positioning my items as I might not use leaflet in the future; I just need to be able to scale/translate my d3.geo.mercator projection so it lines up with leaflet. How can I do this?
Thanks!
Upvotes: 3
Views: 2237
Reputation: 908
Here's what I ended up with (don't be surprised about the strangeness of JS – it's ES6):
const convertZoomLevelToMercator = (zoomLevel) =>
Math.pow(2, 8 + zoomLevel) / 2 / Math.PI;
const convertZoomLevelFromMercator = (zoomLevelInMercator) =>
Math.log(zoomLevelInMercator * 2 * Math.PI) / Math.LN2 - 8;
Testing:
console.log(convertZoomLevelToMercator(1));
console.log(convertZoomLevelToMercator(5));
console.log(convertZoomLevelToMercator(10));
console.log(convertZoomLevelToMercator(15));
console.log(convertZoomLevelToMercator(20));
console.log('----');
console.log(convertZoomLevelFromMercator(convertZoomLevelToMercator(1)));
console.log(convertZoomLevelFromMercator(convertZoomLevelToMercator(5)));
console.log(convertZoomLevelFromMercator(convertZoomLevelToMercator(10)));
console.log(convertZoomLevelFromMercator(convertZoomLevelToMercator(15)));
console.log(convertZoomLevelFromMercator(convertZoomLevelToMercator(20)));
Output:
81.48733086305042
1303.797293808806
41721.51340188181
1335088.428860218
42722829.72352698
----
1
5
10
15
20
Upvotes: 1
Reputation: 1250
Map.projection = d3.geo.mercator()
.center([Map.center[1], Map.center[0]])
.scale((1 << 8 + Map.zoom) / 2 / Math.PI)
.translate([Map.width / 2, Map.height / 2])
Not sure how that works, but looked at some other examples and figured it out.
Upvotes: 4