使用 D3 的 Geojson 地图仅渲染要素集合中的单个路径

IT技术 javascript d3.js geojson
2021-03-12 21:44:30

我正在尝试绘制哥伦比亚某些地区的 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')

这是我的完整代码:

https://plnkr.co/edit/kSDtyyoWr9TSEDZ5Letv?p=preview

3个回答

问题

您的所有功能都在绘制,您正在正确使用您的路径并进入循环。要查看,请将填充设置为无:

在此处输入图片说明

您可以在检查 svg 时看到它们:所有路径都在那里。

当它们填满时,你为什么不在地图上看到它们?因为多边形是倒置的,所以它们覆盖了除感兴趣区域之外的整个世界。虽然大多数其他地理库/渲染器将 geojson 视为笛卡尔,但 D3 没有。这意味着绕线顺序很重要。您的坐标以错误的顺序缠绕。

解决方案

要正确填充、绘制所有要素并支持鼠标交互,您需要反转多边形的缠绕顺序。您可以即时执行此操作,也可以创建新的 geojson 文件来存储预反转数据。

为此,让我们看看您的数据。您仅使用 MultiPolygons 的功能,让我们看一下结构:

{ 
  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

它正在绘制所有路径。在网页检查器中查看 SVG 的 DOM 进行确认。但是,由于填充,您只能看到顶部的区域恰好是较大的区域。尝试添加.style('fill', 'none')到 JS 中的路径添加。或 CSS 中的以下内容

path {
  fill: none
}
@AndrewReid 绝对。需要明确的是,这不是你应该做的。相反,它是为什么您无法在 SVG 中看到其他路径的答案。反转渲染/环顺序确实是解决它的方法
2021-04-23 21:44:30
虽然这确实可以治疗症状,但它实际上并没有解决根本原因:缠绕顺序,将填充更改为无将限制选项,例如创建等值线或允许每个区域的鼠标交互。
2021-05-08 21:44:30

如果有人会看到类似的问题,我创建了一个可以帮助您rewindreversegeojson的工具

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>