1

I am drawing a map of the United States,Costa Rica and Canada. And I would like the maps to adapt to the size of the div#statesvg

<div id="statesvg" style="width:100%; height:100%"></div>

the size of div#statesvg is dynamic.

I only want by default that the maps fits exactly to the div that contains it.

I'm trying to center each map, but it's not centered. I would like to know if there is any mathematical formula or something to scale the map until it fully occupies the svg container.

  if(json=="usa.json"){
  // D3 Projection
    var projection = d3.geo.albersUsa()
                   .translate([width/2, height/2])
                   .scale((height*1.25));
  }

  if(json=="canada.json"){
  //canada lat long 54.6965251,-113.7266353 
    var projection = d3.geo.mercator()
             .center([-113.7266353,54.6965251   ])
                   .translate([width/2, height/2])
                   .scale((height*1.25));
  }

  if(json=="costarica.json"){
  //costa rica lat long
    var projection = d3.geo.mercator()
             .center([-87.0531006,8.351569  ])
                   .translate([width/2, height/2])
                   .scale((height*1.25));
  }          
  // Define path generator
  var path = d3.geo.path()               // path generator that will convert GeoJSON to SVG paths
             .projection(projection);  // tell path generator to use albersUsa projection

enter image description here

this is my actual problem for each map

enter image description here

thanks!

this is my code:

http://plnkr.co/edit/lJgx0fbLcEh7e4W3j6XD?p=preview

yavg
  • 2,761
  • 7
  • 45
  • 115
  • I don't think it's a duplicate (at least not of the proposed duplicate). – Xavier Guihot Mar 07 '18 at 21:24
  • 1
    @yavg, you are right not a duplicate of the one I linkd.. I've re-opened it. This question has been asked many times though. – Mark Mar 07 '18 at 21:25
  • @Mark Thanks, but in this case, it is a question that many users can help. At least in my case I have seen examples of how to center the map (I do not know what I am doing wrong), but I do not know how to scale it to fit the container. It is a question that solves two problems in one. I would really appreciate it if you can help me please. – yavg Mar 07 '18 at 21:49
  • @XavierGuihot thank you very much friend. Thank you for first reading and not judging. I hope you can help me. – yavg Mar 07 '18 at 21:50

1 Answers1

1

There is this nice gist from nrabinowitz, which provides a function which scales and translate a projection to fit a given box.

It goes through each of the geodata points (data parameter), projects it (projection parameter), and incrementally update the necessary scale and translation to fit all points in the container (box parameter) while maximizing the scale:

function fitProjection(projection, data, box, center) {
  ...
  return projection.scale(scale).translate([transX, transY])
}

I've adapted part of your code (the Canada map) to use it:

d3.json("canada.json", function(data) {

  var projection =
    fitProjection(d3.geo.mercator(), data, [[0, 0],  [width, height]], true)

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

  d3.select("#statesvg svg").remove();

  var svg = d3.select("#statesvg").append("svg")
    .attr("width", width+"px")
    .attr("height", height+"px");

  svg.selectAll("path")
    .data(data.features)
    .enter()
    .append("path")
    .attr("d", path)
    .style("stroke", "#fff")
    .style("stroke-width", "1")
    .style("fill", function(d) { return "rgb(213,222,217)"; });
});

As commented by the author, it seems to only work for Mercator projections.

Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190