d3 create a custom compressed projection based on the mercator projection - d3.js

How do i create a custom projection based on the mercator projection which is compressed / scaled in the y-Axis ?
Right now I am using a TopoJson with this projection
var projection = d3.geo.mercator()
.rotate([96, 0])
.center([-.6, 38.7])
.scale(1070)
.translate([width / 2, height / 2]);
Do I have to use the d3.geo.projectionMutator or d3.geo.stream ?

Related

Zoom world map in D3 upto particular level Around a given latitude and longitude

Is there any way that I can focus into d3 world Map around a specific latitude and longitude on load of file.
Here is working plunker in which I can zoom around a d3 world Map.
plunker
Below code is used to zoom in for click.
function clicked() {
currScale2 = projection.scale();
if(beforeClickValue == 0)
beforeClickValue = 150;
beforeClickValue = beforeClickValue + 100;
projection.scale(beforeClickValue);
g.selectAll("path").attr("d", path);
}
I need to zoom in near or around Kenya, if I provide a particular location in Kenya, eg:
Latitude 0.55378653650984688
Longitude 35.661578039749543
If your centering point is determined by a feature
If your point is a feature centroid, then you can automatically center your map using that feature:
There are a few ways to achieve this, one would be to set your projection to be centered on your features:
projection.fitSize([width,height],geoJSONKenyaTurkana);
fitSize takes the width and height of a bounding box - your svg - and sets the scale and translate of the projection to maximize the size of the features within that bounding box. .fitExtent will allow a bit more flexibility regarding margins:
projection.fitExtent([[10,10],[width-10,height-10]],geoJSONKenyaTurkana);
This will provide margins of 10 pixels: the first coordinate is the top left of the bounding box, while the second coordinate is the bottom right.
After setting your projection to be centered with either method, then you can append the features - your zoom constraints, however, will be relative to this starting point - as you have zoomed in on the projection. Here's a plunkr with this approach (using fitSize):
https://plnkr.co/edit/E7vqcwwISmmxUarCsWvw?p=preview
I've used your featureCollection as the feature, but you could center it on an individual feature in the feature collection.
Alternatively, and possibly more in line with your title, you can use a zoom identity to set the intitial zoom factor with d3.zoom, this manipulates the svg rather than the projection and uses your zoom function:
var bounds = path.bounds(geoJSONKenyaTurkana),
dx = bounds[1][0] - bounds[0][0],
dy = bounds[1][1] - bounds[0][1],
x = (bounds[0][0] + bounds[1][0]) / 2,
y = (bounds[0][1] + bounds[1][1]) / 2,
scale = .9 / Math.max(dx / width, dy / height),
translate = [width / 2 - scale * x, height / 2 - scale * y];
svg.call(_zoom.transform, d3.zoomIdentity
.scale(scale)
.translate(translate[0]/scale,translate[1]/scale)
);
This gives us something that looks like this:
https://plnkr.co/edit/CpL4EDUntz853WzrjtU0?p=preview
If you want to manually set a centering point
If however, you want to set your map to be centered according to a manually set point, you can accomplish this much the same way as above: modifying the projection, or modifying the zoom:
To modify the projection, you can use .center() which takes a coordinate and centers the map on this point:
projection.center([longitude,latitude])
Of course, points don't have area, so you will have to set the scale factor yourself, the value will depend on what you want to show:
projection.center([longitude,latitude]).scale(k);
Larger values are more zoomed in.
Alternatively, to manipulate the zoom function, we can use something like:
var x = projection([35.661578039749543,0.55])[0],
y = projection([35.661578039749543,0.55])[1],
scale = 20,
translate = [width / 2 - scale * x, height / 2 - scale * y];
svg.call(_zoom.transform, d3.zoomIdentity
.scale(scale)
.translate(translate[0]/scale,translate[1]/scale)
);
As with setting the projection to center on a specific point, you'll need to set a scale value manually. Here I've arbitrarily chosen 20.

How can I add space between features in d3 geo projections

I have a simple d3 geojson projection here. I am using the following for my scaling...
var projection = d3.geo.albersUsa()
.translate([$scope.width / 2, $scope.height / 2]);
Is there a way to add a margin between the state "features" in this projection. So say I want 10px between the borders of every state.

D3 - Centering Map Using Lat/Lon Origin

This is now driving me insane. I've read pretty much all the posts on this, and still cannot work out how to do it efficiently, i.e. not trial and error.
I have a map of Sweden, and I basically want to zoom into the map using a lat/lon position as the center point (14.4W, 57.2N). My projection variable settings are as follows:
var projection = d3.geo.albers()
.center([0, 57.2])
.rotate([14.4, 0])
.parallels([50, 60])
.scale(900 * 3)
.translate([width / 2, height / 2]);
At the default scale (150), the map centers properly. When I try to scale up however, I don't understand why the 14.4W, 57.2N position is not remaining in the center of the canvas?
Can anyone please shed some light? The full Gist code is here Sweden map Gist and the block is here Sweden map block

How to scale a TopoJSON map in d3.js

In this JSBin, I have a d3.js chloropleth; unlike with a chart, when I change the height and width only the canvas size changes. How do I get the map to scale down as well?
Have a look at the "Let's Make a Map" Tutorial.
You want to define a projection for your path, depending on its type (likely albersUSA in your case):
var projection = d3.geo.albersUsa()
.scale(800)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
You will need to translate the map as needed.

Let's make a map tutorial, stuck at projection step

I'm trying to recreate a map of the Netherlands from Mike Bostock's tutorial. I get the first step done and actually see the smaller map. But when I go to the second step and try to change the projection everything is blank. Is it possible that this is caused by the data including the Dutch Antilles? They are so far it apart that I might be looking at the ocean?
My files
It seems to me that setting the center attribute on the projection was messing things up, it might be because your data was crossing date line? I notice the the bounding box stretch way off to the south and west.
My approach was to set the scale and translation based on one of the centrally located provinces. The scale and translation were automatically calculated based on Mike's code in this stack overflow question. The idea is to use a unit projection and then to calculate the bounds of a given feature. These bounds are then used to calculate appropriate scale and translation (avoiding using the center attribute). The projection is then updated using the recalculated scale and transform.
The relevant code is:
//select a province to center on
var l = topojson.feature(nld, nld.objects.subunits).features[8],
//calculate the bounds
b = path.bounds(l),
//calculate the scale based on the bounds (note that I've set the proportion to
//less than one so you can see all of the Netherlands)
s = .125 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
//calculate the translation based on the bounds
t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];
//update the projection
projection
.scale(s)
.translate(t);
And you can find an example here

Resources