D3.js - JSON数据数组将相同的数组元素绑定到所有内容

16

我正在加载一个包含一组对象的GeoJSON数据文件,每个对象都包含不同国家轮廓的矢量信息。同一数组元素被绑定到每个DOM元素。我以前在JavaScript中遇到过这个作用域问题,但是我所做的每一个更改都导致没有加载任何内容。

我附加了一个jsfiddle。我使用的示例数据文件似乎需要几秒钟才能加载。

我的jsfiddle代码如下:

$(document).ready(function() {
  d3.json(
    "https://raw.githubusercontent.com/datasets/geo-boundaries-world-110m/master/countries.geojson",
    function(error, data) {
      var myGeoJSON = data.features;

      for (i = 0; i < myGeoJSON.length; i++) {
        var path = d3.geo.path();
        var width = 960;
        var height = 600;
        var svg = d3.select("body").append("svg")
          .attr("width", width)
          .attr("height", height);

        svg.selectAll("path")
          .data(data.features)
          .enter().append("path")
          .attr("d",path)
          .attr("fill","#3e429a");
      }
    }
  );
});

抱歉,我会编辑一下,如果我增加i的话它就会出错,稍后回来报告错误。 - Four_lo
d3 返回“无法读取未定义的长度” - Four_lo
那么,我假设你已经检查过数据了? - Cool Blue
1
数据看起来没问题,你可以使用类似 .data([data.features[i]]) 的方式逐个加载多边形。然后你还需要将视图居中于国家(向下滚动一点以查看一些聚焦的国家)。 - Pinguin Dirk
你给我们的地理数据文件只包含了美国的数据...移除for循环后,它会正确地显示一个国家。 - honerlawd
显示剩余2条评论
1个回答

12

您不需要循环遍历特征数组。您的数据文件是一个FeatureCollection,可以D3绘制,可以将其作为单个路径元素:

svg.append("path").datum(data).attr("d", d3.geo.path());

或者作为单独的路径元素,每个特征(国家)一个。
svg.selectAll("path").data(data.features)
  .enter().append("path").attr("d", d3.geo.path())

默认情况下,D3使用投影d3.geo.albersUsa(),该投影将夏威夷移到墨西哥,将阿拉斯加移到热带区域以外。您可以切换到等经纬度投影以查看整个世界:

d3.json(
  "https://raw.githubusercontent.com/datasets/geo-boundaries-world-110m/6cf0946a0f4d027d21686e8402f19b524c4f6385/countries.geojson",
  function(error, data) {
    var projection = d3.geo.equirectangular();
    var path = d3.geo.path().projection(projection);
    var width = 960;
    var height = 600;
    var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height);

    svg.selectAll("path")
      .data(data.features)
      .enter().append("path")
      .attr("d", path)
      .attr("fill", "#3e429a");
  }
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>


结语:我最初尝试使用更常见的墨卡托投影,但发现它无法处理南极洲。D3绘制了大陆的形状,然后填充其余的海洋。

在同一个D3论坛帖子中,D3的作者提到了TopoJSON工具中的一个错误,这可能与您使用的数据文件有关。如果您喜欢墨卡托投影,则可能需要与geo-boundaries-world-110m的维护者合作修复数据文件,或者仅从您的地图中排除南极洲。

墨卡托投影下南极洲的演示:

d3.json(
  "https://raw.githubusercontent.com/datasets/geo-boundaries-world-110m/6cf0946a0f4d027d21686e8402f19b524c4f6385/countries.geojson",
  function(error, data) {
    var projection = d3.geo.mercator();
    var path = d3.geo.path().projection(projection);
    var width = 960;
    var height = 600;
    var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height);

    var antarctica = data.features.splice(6, 1);
    // now "data" has the rest of the world
    svg.selectAll("path")
      .data(antarctica)
      .enter().append("path")
      .attr("d", path)
      .attr("stroke", "red").attr("stroke-width", 10)
      // thick borders so we can see the odd paths
      .attr("fill", "#3e429a");
  }
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>


今天我了解到 d3.geo.equirectangular 的存在。谢谢。 - azz
@approxiblue。谢谢您。我本来会抓狂好几周的。您能否随口推荐一些调试D3的工具,特别是用于监视控制器和视图之间发生的情况?我对d3和将d3数据绑定到视图的过程都很陌生。 - Four_lo
@Four_lo 你可以在一个位置函数中放置console.log调用。再加上浏览器的JS调试器(将代码分成多行,以便您可以在更多地方设置断点)。我没有经常使用D3需要更专业的工具。 - approxiblue
@approxiblue 很好!谢谢你,我很感激你的帮助。 - Four_lo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接