I’m trying to draw a map in an SVG with the GEOJSON data that I bring from this API, the SVG paths are filled with the data, however, the SVG is blank, as can be seen when executing the code below. Notice the document.write
, the data is returned correctly.
var svg = d3.select("svg") d3.json('https://api.mocki.io/v1/d214eb47') .then(data => { svg.append('g') .selectAll('path') .data(data.features) .enter() .append('path') .attr('d', d3.geoPath().projection(d3.geoMercator())) document.write(JSON.stringify(data)); })
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script> <svg width="600" height="600"></svg>
I tested it with another GEOJSON file, and managed to draw in SVG as seen when executing the code below:
const link = "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson"; var svg = d3.select("svg") d3.json(link) .then(data => { svg.append("g") .selectAll("path") .data(data.features) .enter() .append("path") .attr("d", d3.geoPath() .projection(d3.geoMercator()) ) //document.write('data ', JSON.stringify(data)) });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script> <svg width="600" height="600"></svg>
Does anyone know what’s wrong with the first code snippet?
Advertisement
Answer
There is no issue in the data, the problem here is just that you’re trying to map a very small region (San Francisco), unlike the world map in your second example. That said, you should set the scale
and the center
of the projection. In your case:
const projection = d3.geoMercator() .scale(100000) .center([-122.3, 37.75])
The resulting code:
var svg = d3.select("svg"); const projection = d3.geoMercator() .scale(100000) .center([-122.3, 37.75]) d3.json('https://api.mocki.io/v1/d214eb47') .then(data => { svg.append('g') .selectAll('path') .data(data.features) .enter() .append('path') .attr('d', d3.geoPath().projection(projection)) })
path { fill: wheat; stroke: darkslateblue; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script> <svg width="600" height="600"></svg>
But it’s way easier just using fitExtent
with your SVG width and height:
const projection = d3.geoMercator() .fitExtent([ [0, 0], [600, 600] ], data)
And here is the resulting code:
var svg = d3.select("svg"); d3.json('https://api.mocki.io/v1/d214eb47') .then(data => { const projection = d3.geoMercator() .fitExtent([ [0, 0], [600, 600] ], data) svg.append('g') .selectAll('path') .data(data.features) .enter() .append('path') .attr('d', d3.geoPath().projection(projection)) })
path { fill: wheat; stroke: darkslateblue; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script> <svg width="600" height="600"></svg>