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>