使用 D3 的 Geojson 地图仅在要素集合中呈现单个路径
Geojson map with D3 only rendering a single path in a feature collection
我正在尝试绘制哥伦比亚某些地区的 geojson 地图。目前它只显示一条路径:,
我的特征集有52个特征,但我只能画出这个特征。我不知道我做错了什么,我的代码基于其他教程。我该怎么做才能显示所有路径?
var features = mapData.features;
console.log(features);
// Update color scale domain based on data
// Draw each province as a path
mapLayer.selectAll('path')
.data(features)
.enter().append('path')
.attr('d', path)
.attr('vector-effect', 'non-scaling-stroke')
这是我的完整代码:
正在绘制所有路径。在网页检查器中查看 SVG 的 DOM 以确认。但是,由于填充,您只能看到顶部区域恰好是较大的区域。尝试将 .style('fill', 'none')
添加到 JS 中的路径添加中。或 CSS
中的以下内容
path {
fill: none
}
问题
您所有的功能都在绘制,您正确使用了您的路径并进入了循环。要查看,请将填充设置为 none:
您可以在检查 svg 时看到它们:所有路径都在那里。
为什么填满后在地图上看不到它们?因为多边形是倒置的,所以它们覆盖了整个世界,除了感兴趣的区域。虽然大多数其他地理 libraries/renderers 将 geojson 视为笛卡尔坐标,但 D3 不会。这意味着绕组顺序很重要。您的坐标以错误的顺序缠绕。
解决方案
要正确填充、绘制所有要素并支持鼠标交互,您需要反转多边形的缠绕顺序。您可以即时执行此操作,或创建新的 geojson 文件来存储预反转数据。
为此,让我们看一下您的数据。您只使用多边形特征,让我们看一下结构:
{
type:"Feature",
properties: {...},
geometry: {
type: "MultiPolygon",
coordinate: /* coordinates here */
}
}
坐标结构如下:
coordinates:[polygons] // an array of polygons
各个多边形的结构如下:
[outer ring][inner ring][inner ring]... // an array of coordinates for an outer ring, an array of coordinates for each hole (inner ring).
多边形环的结构为长纬度数组,第一个值和最后一个值相同。
[x,y],[x,y]....
因此,要反转坐标的顺序,我们需要反转环形数组中的项目:
features.forEach(function(feature) {
if(feature.geometry.type == "MultiPolygon") {
feature.geometry.coordinates.forEach(function(polygon) {
polygon.forEach(function(ring) {
ring.reverse();
})
})
}
})
如果我们也有多边形混合(它们的嵌套稍微少一些),我们可以使用:
features.forEach(function(feature) {
if(feature.geometry.type == "MultiPolygon") {
feature.geometry.coordinates.forEach(function(polygon) {
polygon.forEach(function(ring) {
ring.reverse();
})
})
}
else if (feature.geometry.type == "Polygon") {
feature.geometry.coordinates.forEach(function(ring) {
ring.reverse();
})
}
})
这是更新后的 plunker
如果有人看到类似的问题,我创建了一个工具来帮助您 rewind
或 reverse
geojson
https://observablehq.com/@bumbeishvili/rewind-geojson
您可以运行将其作为下面的片段
<div class="notebook-content">
</div>
<script type="module">
import notebook from "https://api.observablehq.com/@bumbeishvili/rewind-geojson.js"; // "download code" url
document.querySelector('.notebook-content').innerHTML =notebook.modules[0].variables
.filter(d=>d)
.map((d,i)=>` <div class=" observable-wrapper div-number-${i}"></div>`)
.join('')
.concat('<div style="display:none" class="hidden"></div>')
import {Inspector, Runtime} from "https://unpkg.com/@observablehq/runtime@3/dist/runtime.js";
let i=1;
Runtime.load(notebook, (variable) => {
if(i==4 ){i++; return new Inspector(document.querySelector(`.hidden`));}
if(i==13)return;
return new Inspector(document.querySelector(`.observable-wrapper:nth-child(${i++})`));
});
</script>
我正在尝试绘制哥伦比亚某些地区的 geojson 地图。目前它只显示一条路径:,
我的特征集有52个特征,但我只能画出这个特征。我不知道我做错了什么,我的代码基于其他教程。我该怎么做才能显示所有路径?
var features = mapData.features;
console.log(features);
// Update color scale domain based on data
// Draw each province as a path
mapLayer.selectAll('path')
.data(features)
.enter().append('path')
.attr('d', path)
.attr('vector-effect', 'non-scaling-stroke')
这是我的完整代码:
正在绘制所有路径。在网页检查器中查看 SVG 的 DOM 以确认。但是,由于填充,您只能看到顶部区域恰好是较大的区域。尝试将 .style('fill', 'none')
添加到 JS 中的路径添加中。或 CSS
path {
fill: none
}
问题
您所有的功能都在绘制,您正确使用了您的路径并进入了循环。要查看,请将填充设置为 none:
您可以在检查 svg 时看到它们:所有路径都在那里。
为什么填满后在地图上看不到它们?因为多边形是倒置的,所以它们覆盖了整个世界,除了感兴趣的区域。虽然大多数其他地理 libraries/renderers 将 geojson 视为笛卡尔坐标,但 D3 不会。这意味着绕组顺序很重要。您的坐标以错误的顺序缠绕。
解决方案
要正确填充、绘制所有要素并支持鼠标交互,您需要反转多边形的缠绕顺序。您可以即时执行此操作,或创建新的 geojson 文件来存储预反转数据。
为此,让我们看一下您的数据。您只使用多边形特征,让我们看一下结构:
{
type:"Feature",
properties: {...},
geometry: {
type: "MultiPolygon",
coordinate: /* coordinates here */
}
}
坐标结构如下:
coordinates:[polygons] // an array of polygons
各个多边形的结构如下:
[outer ring][inner ring][inner ring]... // an array of coordinates for an outer ring, an array of coordinates for each hole (inner ring).
多边形环的结构为长纬度数组,第一个值和最后一个值相同。
[x,y],[x,y]....
因此,要反转坐标的顺序,我们需要反转环形数组中的项目:
features.forEach(function(feature) {
if(feature.geometry.type == "MultiPolygon") {
feature.geometry.coordinates.forEach(function(polygon) {
polygon.forEach(function(ring) {
ring.reverse();
})
})
}
})
如果我们也有多边形混合(它们的嵌套稍微少一些),我们可以使用:
features.forEach(function(feature) {
if(feature.geometry.type == "MultiPolygon") {
feature.geometry.coordinates.forEach(function(polygon) {
polygon.forEach(function(ring) {
ring.reverse();
})
})
}
else if (feature.geometry.type == "Polygon") {
feature.geometry.coordinates.forEach(function(ring) {
ring.reverse();
})
}
})
这是更新后的 plunker
如果有人看到类似的问题,我创建了一个工具来帮助您 rewind
或 reverse
geojson
https://observablehq.com/@bumbeishvili/rewind-geojson
您可以运行将其作为下面的片段
<div class="notebook-content">
</div>
<script type="module">
import notebook from "https://api.observablehq.com/@bumbeishvili/rewind-geojson.js"; // "download code" url
document.querySelector('.notebook-content').innerHTML =notebook.modules[0].variables
.filter(d=>d)
.map((d,i)=>` <div class=" observable-wrapper div-number-${i}"></div>`)
.join('')
.concat('<div style="display:none" class="hidden"></div>')
import {Inspector, Runtime} from "https://unpkg.com/@observablehq/runtime@3/dist/runtime.js";
let i=1;
Runtime.load(notebook, (variable) => {
if(i==4 ){i++; return new Inspector(document.querySelector(`.hidden`));}
if(i==13)return;
return new Inspector(document.querySelector(`.observable-wrapper:nth-child(${i++})`));
});
</script>