d3.js 如何在 div 中拟合多个多边形

d3.js how to fit multiple polygon in a div

刚开始学习d3.js。请多多包涵。我有一个包含多边形集合(可能有数千个)的绘图。我喜欢将它们作为 svg 并根据它们的属性进行着色。

  1. 我在查看 geoJson 时迷路了。我应该使用 geoJson,还是只使用带有点数组的简单 json?
  2. 我试过 mbostock 的 Custom Projection, then my drawing does not fit in my div. also tried Identity projection of map in d3.js, but projection is incorrect, which should be 20 simple box.
  3. 我喜欢在 svg 的后面附加一个图像文件(jpg、png、...)。我应该怎么做?我应该在我的 json/geojson 文件中包含一个边界框以便更容易对齐吗?
  4. 我喜欢使用单独加载的数据为每个多边形着色,我应该怎么做?

这是我的 test json file 地理json 格式

谢谢 韦斯

您可以使用 geojson 以及 geoTransformgeoIdentity 投影。这些用于平面坐标,而通常 d3.geoProjections 用于在地球上取点并将它们投影到平面上。这就是为什么自定义投影可能会导致一些奇怪的形状,具体取决于您如何定义它。

geoIdentity 选项可能是最简单的:它投影平面几何体并让您可以使用 d3 投影方法,如 .fitExtent.fitSize。为此,fitSize 是最合适的,它需要一个 geoJson 对象(featureCollection)并转换和缩放它包含的特征以包含在指定的大小内:.fitExtent([width,height],geoJson object):

var projection = d3.geoIdentity()   
  .fitSize([width,height],data);  // the area the features will be fitted to

fitExtent 可在需要边距时使用,而 .fitSize 假定左侧或顶部没有边距,请参阅文档 here

如果使用 geoIdentity 而没有 .fitSize.fitExtent,您的坐标值将被解释为像素值。如果您的数据方面与 svg 容器的方面不匹配,那么该功能将尽可能以超宽或超高定位(fitSize 不会扭曲方面)。如果将图像放在数据后面,请确保您的图像具有与 svg 相同的纵横比,并且占据相同数量的像素 space.

另一个问题是 geoIdentity 可能会导致某些东西颠倒(因为 svg y 值从顶部的零开始,并随着向下增加而增加,这与许多其他约定相反)。

要翻转 y 使用 reflectY(true) :

 var projection = d3.geoIdentity()
  .reflectY(true)
  .fitSize([width,height],data);

最后,附加时,请务必使用 geoJson.features,否则您会将单个项目绑定到您的输入选择,它将呈现为单个路径。您想要将每个功能绑定到不同的元素。

结合起来,您可以得到一组适当缩放的多边形。请参阅 this block 了解所有内容(我会使用一个片段,但 json 会淹没它)。


虽然我已经为多边形着色以展示每个多边形的范围,但您可以用各种不同的方式为它们着色。您可以将 属性 与定义颜色的每个特征相关联:

{"type":"Feature","id":"loc781","properties":{"color":"yellow"},"geometry":}...

并且在附加多边形时:

.attr("fill", function(d) { return d.properties.color; })

或属性中的一个值,您可以使用该值根据比例进行着色:

{"type":"Feature","id":"loc781","properties":{"value":10},"geometry":}...

var scale = d3.scaleLinear().domain([0,50]).range([yellow,blue])

并且在附加多边形时:

.attr("fill", function(d) { return scale(d.properties.value); })

在我的块示例中,我只使用了序数标度和附加特征的索引:

var color = d3.scaleOrdinal(d3.schemeCategory20);

添加矩形时:

.attr("fill", function(d,i) { return color(i); });


至于将图像放在另一个元素后面,那是在 css 中小心放置的问题。如上所述,只需确保您的 svg 边界、.fitSize 的边界和图像的边界相同。请参阅此 question and answer 以获得潜在的解决方案。


最后,如果放置数千个元素,可能需要切换到 canvas 进行渲染,这很简单,但是另一个问题。