问题
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