d3.js 如何在 div 中拟合多个多边形
d3.js how to fit multiple polygon in a div
刚开始学习d3.js。请多多包涵。我有一个包含多边形集合(可能有数千个)的绘图。我喜欢将它们作为 svg 并根据它们的属性进行着色。
- 我在查看 geoJson 时迷路了。我应该使用 geoJson,还是只使用带有点数组的简单 json?
- 我试过 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.
- 我喜欢在 svg 的后面附加一个图像文件(jpg、png、...)。我应该怎么做?我应该在我的 json/geojson 文件中包含一个边界框以便更容易对齐吗?
- 我喜欢使用单独加载的数据为每个多边形着色,我应该怎么做?
这是我的 test json file 地理json 格式
谢谢
韦斯
您可以使用 geojson 以及 geoTransform
或 geoIdentity
投影。这些用于平面坐标,而通常 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 进行渲染,这很简单,但是另一个问题。
刚开始学习d3.js。请多多包涵。我有一个包含多边形集合(可能有数千个)的绘图。我喜欢将它们作为 svg 并根据它们的属性进行着色。
- 我在查看 geoJson 时迷路了。我应该使用 geoJson,还是只使用带有点数组的简单 json?
- 我试过 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.
- 我喜欢在 svg 的后面附加一个图像文件(jpg、png、...)。我应该怎么做?我应该在我的 json/geojson 文件中包含一个边界框以便更容易对齐吗?
- 我喜欢使用单独加载的数据为每个多边形着色,我应该怎么做?
这是我的 test json file 地理json 格式
谢谢 韦斯
您可以使用 geojson 以及 geoTransform
或 geoIdentity
投影。这些用于平面坐标,而通常 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 进行渲染,这很简单,但是另一个问题。