【问题标题】:D3.js geoPath map returning Error: <path> attribute d: Expected number [duplicate]D3.js geoPath地图返回错误:<path>属性d:预期数字[重复]
【发布时间】:2020-11-16 10:08:26
【问题描述】:

我在 D3.js 中绘制地图时遇到问题

以下代码适用于某些 json 文件,但在我需要使用的数据上,它会返回类似于以下的错误字符串:

错误:属性 d:预期数字,“….21478248741596,NaNL547.70469610…”。

并显示这张图片(虽然漂亮不是我希望的英格兰地图)

这是代码:

const width = 800
const height = 800

const svg = d3.select('svg')
  .append('g')
  .attr('class', 'map');

const projection = d3.geoMercator()

Promise.all([
  d3.json('https://raw.githubusercontent.com/joewretham/d3_map_project/main/Clinical_Commissioning_Groups__April_2019__Boundaries_EN_BUC.json')
]).then(
  d => ready(null, d[0], d[1])
);

function ready(error, data) {

  var fixed = data.features.map(function(feature) {
    return turf.rewind(feature, {
      reverse: true
    });
  });

  const path = d3.geoPath().projection(projection);

  projection.fitSize([width, height], {
    "type": "FeatureCollection",
    "features": fixed
  })

  svg.append('g')
    .attr('class', 'countries')
    .selectAll('path')
    .data(fixed)
    .enter().append('path')
    .attr('d', path)
    .style('fill', "teal")
    .style('stroke', 'white')
    .style('opacity', 0.8)
    .style('stroke-width', 0.3);
};
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src='https://npmcdn.com/@turf/turf/turf.min.js'></script>
<svg id="partitionSVG" width="800" height="800">"</svg>

有人知道这里发生了什么吗?因为该代码适用于其他数据集,所以我知道这与坐标有关,我猜它们需要以某种方式进行转换,但我对地理数据了解得不够多,不知道该怎么做。

感谢您的任何建议

乔

【问题讨论】:

  • 请使用堆栈 sn-ps 或 JSFiddle/Codepen 将您的代码转换为可运行的 minimal reproducible example。它将帮助我们理解问题并带来更好的答案
  • 您的 JSON 文件有一些不常见的投影。通常,坐标以纬度/经度给出,但有许多不同的投影 - 最常见的是 WGS84(也称为 4326,由它的 ID)。当前的投影似乎距离某个零点以米或英尺为单位。我不知道当前的投影,如果你找到了,你可以将JSON转换为WGS84。
  • 嗨鲁本 - 感谢您的回复。你带我找到解决方案 - 我回到从 (geoportal.statistics.gov.uk/datasets/…) 获取数据的地方,我发现他们可用的 API 具有 WGS84 中的坐标。更新了小提琴 - jsfiddle.net/joe_wretham/fm1ud063/13。感谢您的帮助
  • 太棒了!乐于助人!

标签: javascript json d3.js maps geojson


【解决方案1】:

您的 JSON 文件有一些不常见的投影。通常,坐标以纬度/经度给出。然而,由于许多原因,例如地球是一个球体,球体投影在数学上很困难,存在几种不同的投影。最常见的是 WGS84(根据其 ID 也称为 4326),并使用 lat/long 格式。但是,事实证明存在几个国家系统。在你的情况下,它是英国国家系统OSGB36。

使用this package,我能够将投影从 OSGB36 转换为 WGS84,得到正确的结果:

const width = 800
const height = 800

const svg = d3.select('svg')
  .append('g')
  .attr('class', 'map');

console.log(window);

const projection = d3.geoMercator()

Promise.all([
  d3.json('https://raw.githubusercontent.com/joewretham/d3_map_project/main/Clinical_Commissioning_Groups__April_2019__Boundaries_EN_BUC.json')
]).then(
  d => ready(null, d[0], d[1])
);

function ready(error, data) {
  data = returnExports.toWGS84(data);

  var fixed = data.features.map(function(feature) {
    return turf.rewind(feature, {
      reverse: true
    });
  });

  const path = d3.geoPath().projection(projection);

  projection.fitSize([width, height], {
    "type": "FeatureCollection",
    "features": fixed
  })

  svg.append('g')
    .attr('class', 'countries')
    .selectAll('path')
    .data(fixed)
    .enter().append('path')
    .attr('d', path)
    .style('fill', "teal")
    .style('stroke', 'white')
    .style('opacity', 0.8)
    .style('stroke-width', 0.3);
};
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src='https://npmcdn.com/@turf/turf/turf.min.js'></script>
<script src='https://unpkg.com/proj4@2.6.2/dist/proj4-src.js'></script>
<script src='https://unpkg.com/gbify-geojson@0.2.1/index.js'></script>
<svg id="partitionSVG" width="800" height="800">"</svg>

如果您有权访问文件的生成,您可以更改输入文件一次,或者您可以在必要时调用此函数。

【讨论】:

  • 谢谢鲁本 - 太棒了,你解决了我的问题,我已经了解了投影
  • 技术上 WGS84 不是投影:它是 3D 坐标系,而 OP 的投影数据是 2D - 由于 D3 投影投影数据,您需要取消投影数据在通过 D3 投影之前(就像答案一样)。但是,您也可以使用d3.geoIdentity.fitSize/fitExtent 正确缩放和平移数据,将其视为平面(尽管覆盖其他特征会很困难)而不是取消投影并立即重新投影,这也将消除对turf.rewind 的需要。不错的答案。
  • 很高兴知道,谢谢!
猜你喜欢
  • 1970-01-01
  • 2017-12-04
  • 2016-09-12
  • 2021-12-20
  • 1970-01-01
  • 2020-12-27
  • 2020-04-20
  • 2019-09-23
  • 1970-01-01
相关资源
最近更新 更多