How can I scale my map to fit my svg size with d3 and geojson path data

烂漫一生 提交于 2021-02-05 09:11:43

问题


I am trying to create a d3 SVG that draws a map of New York State and scale it so that it fits the size of my SVG, the issue I am having is that when I use .fitSize([height, width], mapObject) it only returns a NaN error in the console.

the topoJSON file of NYS I am using

I am able to get the map to display without scaling but of course, it is not optimized and needs to be scaled

I have attempted what is said in this post but I have not figured out the correct solution

var map = d3.json('./ny.json')

Promise.all([map]).then(data => {
  var height = 800;
  var width  = 800;
  var mapData = data[0]

  // original geoJSON to that works without scaling 
  // var geoData = topojson.feature(mapData, mapData.objects["cb_2015_new_york_county_20m"]).features
  //

  var geoData = topojson.feature(mapData, {
    type:"GeometryCollection",
    geometries: mapData.objects["cb_2015_new_york_county_20m"].geometries,
  })

  var projection = d3.geoMercator()
                     .fitSize([width, height], geoData)

  var path = d3.geoPath()
               .projection(projection)

  d3.select('svg')
    .attr('height', height)
    .attr('width', width)
    .selectAll('.county')
      .data(geoData)
      .enter()
      .append('path')
        .classed('.county', true)
        .attr('d', path)

})

I am pretty sure this is a formatting error on my part, but I am unsure of what data .fitSize() or .fitExtent() is trying to compare against.

right now the way the code site I receive no error outputted to the console but I also have no data append to the SVG


回答1:


The issue is that fitSize takes a geojson object while selectAll.data() takes an array, you are using one of these two for both in geoData. This leaves two solutions:

Solution 1:

If we use

var geoData = topojson.feature(mapData, mapData.objects["cb_2015_new_york_county_20m"]).features

var projection = d3.geoMercator()
                 .fitSize([width, height], geoData)

We get NaN errors because the projection is not set properly as we aren't passing a geojson object, just an array of geojson objects. We could solve this by making a feature collection with geoData and passing that to fitSize:

var geoData = topojson.feature(mapData, mapData.objects["cb_2015_new_york_county_20m"]).features

var projection = d3.geoMercator()
     .fitSize([width, height], {type:"FeatureCollection", features: geoData})

Now we are passing a geojson feature collection to fitSize, we're all go on the projection, and since geoData is still an array, we can pass that to selectAll.data() unchanged.

Here's a block.

Solution 2:

If we use:

var geoData = topojson.feature(mapData, {
  type:"GeometryCollection",
  geometries: mapData.objects["cb_2015_new_york_county_20m"].geometries,
})

We get a geojson object, projection.fitSize works, but selectAll().data(geoData) doesn't add any features as it isn't an array - the enter selection is empty. We can substitute in selectAll().data(geoData.features) to solve this and enter one path per feature (alternatively we could use .data([geoData]) to enter one feature for all the paths).

Here's a block.

Both blocks are drawn at the correct scale - the map exceeds the block bounds as I didn't alter your 800x800 dimensions



来源:https://stackoverflow.com/questions/55972289/how-can-i-scale-my-map-to-fit-my-svg-size-with-d3-and-geojson-path-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!