简体   繁体   English

如何用 D3.js 绘制 SVG?

[英]How to make to drawing a SVG with D3.js?

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. 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.注意document.write ,数据正确返回。

 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:我用另一个 GEOJSON 文件对其进行了测试,并设法在 SVG 中绘制,如下面的代码所示:

 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?有谁知道第一个代码片段有什么问题?

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.数据没有问题,这里的问题只是你试图 map 一个非常小的区域(旧金山),与第二个示例中的世界 map 不同。 That said, you should set the scale and the center of the projection.也就是说,您应该设置投影的scalecenter 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:但是将fitExtent与 SVG 宽度和高度一起使用会更容易:

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>

Your GeoJSON file has very small areas that are displayed but with practically zero size shapes in given projection and default SVG viewBox.您的 GeoJSON 文件显示的区域非常小,但在给定的投影和默认的 SVG 视图框中,形状几乎为零。

Check how I've found the boundaries of the SVG G element with your geodata.检查我如何使用您的地理数据找到 SVG G 元素的边界。 I then used that to define SVG viewBox attribute.然后我用它来定义 SVG viewBox 属性。 If SVG width or height are not set then SVG will expand to available "container" size.如果 SVG 宽度或高度未设置,则 SVG 将扩展为可用的“容器”大小。 So you can add a surrounding DIV element and set its size if you wish (fitting SVG in your container and thus in your layout).因此,您可以添加一个周围的 DIV 元素并根据需要设置其大小(将 SVG 安装在您的容器中,从而在您的布局中)。

UPDATE: you can even change the SVG viewBox attribute later with javascript by using returned values from the getBBox() function.更新:您甚至可以稍后使用 getBBox() function 的返回值使用 javascript 更改 SVG viewBox 属性。 The other possibility in another answer is of course great, too (fitting extent of your SVG).另一个答案中的另一种可能性当然也很好(SVG的拟合程度)。

 var svg = d3.select("svg"); const link = "https://api.mocki.io/v1/d214eb47"; //const link = "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/world.geojson"; d3.json(link).then(data => { svg.append('g').selectAll('path').data(data.features).enter().append('path').attr('d', d3.geoPath().projection(d3.geoMercator())); //console.log(data.features); console.log(document.getElementsByTagName("g")[0].getBBox()); })
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.6.0/d3.min.js"></script> <svg viewBox="152.95315551757812 140.7493133544922 0.421722412109375 0.4228363037109375"></svg>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM