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

时间:2017-11-01 21:35:55

标签: json d3.js geojson

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

  1. 我正在看geoJson并迷路了。我应该使用geoJson,还是只使用点数组数组的简单json?
  2. 我尝试了mbostock的Custom Projection,然后我的绘图不适合我的div。还试过Identity projection of map in d3.js,但投影不正确,应该是20个简单框。 enter image description here
  3. 我喜欢在svg后面添加一个图像文件(jpg,png,...)。我该怎么办?我应该在我的json / geojson文件中包含一个boundbox,以便更容易对齐吗?
  4. 我喜欢为每个多边形着色使用单独加载的数据,我应该怎么做?
  5. 这是geojson格式的test json file

    由于 韦斯

1 个答案:

答案 0 :(得分:1)

您可以使用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具有相同的纵横比,并占用相同数量的像素空间。

另一个问题是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

最后,如果放置数千个元素,可能需要切换到画布进行渲染,这很简单,但问题却不同。

相关问题