Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 - Center and scale sector on map

I am having some issues that I can not seem to sort out, For the sake of keeping this simple I will only use some stock examples to explain what I am looking to do.

http://bl.ocks.org/mbostock/5126418 -- This basic functionality

What i am looking to do is when a "Tract" is clicked on the map is hidden and the selected Tract is centered on the screen and expanded

My problem is that every time I try this the selected object is just pushed off the screen.

I am sure I am doing something wrong I am new to D3 and have only been using it for a few days

.on("click", function(d){
    svg
    .append("g")
    .attr("id", "tract")
    .append("g")
    .attr("id", "wrapper")
    .selectAll("path")
    .data([d])
  .enter()
    .append("path")
    .attr("d", path)
    .attr("id", "tract"),
d3.select("#wrapper")
            .transition()
            .duration(800)
            .ease("cubic-bezier(0.785, 0.135, 0.150, 0.860)")
            .attr("transform", "scale(" + 3 + "), translate(" + (width/2) + ", " + (height/2) + ")");
})

This has been driving me nuts so any help would be greatly appreciated.

like image 721
Recursive Avatar asked Dec 12 '25 08:12

Recursive


1 Answers

I'm also very new to d3 - will try to explain how I understand it but I'm not sure I got everything right.

The projection has the concept of a center, given in map units:

projection.center([location])

If center is specified, sets the projection’s center to the specified location, a two-element array of longitude and latitude in degrees and returns the projection. If center is not specified, returns the current center which defaults to ⟨0°,0°⟩.

There is also the translation, which is where in the screen the projection center stands, in pixels.

projection.translate([point])

If point is specified, sets the projection’s translation offset to the specified two-element array [x, y] and returns the projection. If point is not specified, returns the current translation offset which defaults to [480, 250]. The translation offset determines the pixel coordinates of the projection’s center. The default translation offset places ⟨0°,0°⟩ at the center of a 960×500 area.

The secret is knowing that some methods operate on the cartographic space and others on the canvas.

In order to center a feature in the canvas, like to set the projection center to the center of the feature bounding box - this works for mercator (WGS 84, used in google maps), not sure about other projections.

For example, given a projection and path:

var projection = d3.geo.mercator()
    .scale(1);

var path = d3.geo.path()
    .projection(projection);

The bounds method from path returns the bounding box in pixels. Use it to find the correct scale, comparing the size in pixels with the size in map units (0.95 gives you a 5% margin over the best fit for width or height):

var b = path.bounds(feature),
    s = 0.95 / Math.max(
                   (b[1][0]-b[0][0])/width, 
                   (b[1][1]-b[0][1])/height
               );

Use the d3.geo.bounds method to find the bounding box in map units:

b = d3.geo.bounds(feature);

Set the center of the projection to the center of the bounding box:

projection.center([(b[1][0]+b[0][0])/2, (b[1][1]+b[0][1])/2]);

Use the translate method to move the center of the map to the center of the canvas:

projection.translate([width/2, height/2]);

By now you should have the feature in the center of the map zoomed with a 5% margin.

like image 136
Paulo Scardine Avatar answered Dec 16 '25 11:12

Paulo Scardine