添加到D3 Globe的新路径

时间:2017-01-14 09:13:20

标签: javascript jquery d3.js

我正在研究D3 Globe的实施。我正在尝试在用户单击按钮时向地球添加路径,但这并不能证明是成功的。如果我一次添加所有路径没有问题,但如果我尝试在触发事件后添加它们,那么它将失败。我的jsfiddle:http://jsfiddle.net/Guill84/b6xvj76e/1/。我不认为JSON存在问题,因为它会按照预期在控制台中弹出。

失败的脚本可以在小提琴的底部找到。我将其粘贴在下面以便于参考:

$("#clickMe").click(function() {
  data = {
    "type": "FeatureCollection",
    "features": [{
      "type": "Feature",
      "properties": {
        "name": "path1"
      },
      "year": "2010",
      "geometry": {
        "type": "Polygon",
        "coordinates": "[[[116.4551,40.2539],[117.5977,44.3408],[116.4551,40.2539]]]"
      },
      "id": "RML"
    },
    {
      "type": "Feature",
      "properties": {
        "name": "path2"
      },
      "year": "2010",
      "geometry": {
        "type": "Polygon",
        "coordinates": "[[[116.4551,40.2539],[122.3438,41.0889],[116.4551,40.2539]]]"
      },
      "id": "RML"
    },
    {
      "type": "Feature",
      "properties": {
        "name": "path3"
      },
      "year": "2010",
      "geometry": {
        "type": "Polygon",
        "coordinates": "[[[116.4551,40.2539],[105.9961,37.3096],[116.4551,40.2539]]]"
      },
      "id": "RML"
    },
    {
      "type": "Feature",
      "properties": {
        "name": "path4"
      },
      "year": "2010",
      "geometry": {
        "type": "Polygon",
        "coordinates": "[[[116.4551,40.2539],[109.5996,35.6396],[116.4551,40.2539]]]"
      },
      "id": "RML"
    }]}



  console.log(data);
  var svg = d3.select("#body");


  flows = svg.selectAll("path")
    .data(data)
    .enter().append("svg:path")
    .attr("d", clip)
    .style("stroke", "black")
    .attr("id", function(d) {
      return d.properties.name.split(' ').join('_')
    });


});

1 个答案:

答案 0 :(得分:1)

问题是三个:

1)您的JSON结构存在问题:数组以字符串格式指定,因此clip函数使用时会导致错误。

2)您正在绑定data对象,而应该绑定data.features,这是包含您需要创建的四个路径的数组。

3)选择将选择国家的现有路径。您可以通过向新路径添加类来避免这种情况。例如,将它们归类为flow

4)流路径在其渲染函数的范围内声明,因此无法在刷新函数上更新它们。

以下是您的代码,其中包含三个修复程序:

$("#clickMe").click(function () {
    // 1) Arrays: Fixed arrays for coordinates so they are not serialized in a string
    var data = {
        "type": "FeatureCollection",
        "features": [
            {
                "type": "Feature",
                "properties": {
                    "name": "path1"
                },
                "year": "2010",
                "geometry": {
                    "type": "Polygon",
                    "coordinates": [[[116.4551, 40.2539], [117.5977, 44.3408], [116.4551, 40.2539]]]
                },
                "id": "RML"
            },
            {
                "type": "Feature",
                "properties": {
                    "name": "path2"
                },
                "year": "2010",
                "geometry": {
                    "type": "Polygon",
                    "coordinates": [[[116.4551, 40.2539], [122.3438, 41.0889], [116.4551, 40.2539]]]
                },
                "id": "RML"
            },
            {
                "type": "Feature",
                "properties": {
                    "name": "path3"
                },
                "year": "2010",
                "geometry": {
                    "type": "Polygon",
                    "coordinates": [[[116.4551, 40.2539], [105.9961, 37.3096], [116.4551, 40.2539]]]
                },
                "id": "RML"
            },
            {
                "type": "Feature",
                "properties": {
                    "name": "path4"
                },
                "year": "2010",
                "geometry": {
                    "type": "Polygon",
                    "coordinates": [[[116.4551, 40.2539], [109.5996, 35.6396], [116.4551, 40.2539]]]
                },
                "id": "RML"
            }
        ]
    };

    console.log(data);

    var svg = d3.select("#body");

    // 3) Selection: Add a class to avoid collision with existing paths
    // 4) Using var declared outside so it can be used on the update function
    flows = svg.selectAll("path.flow")
        // 2) Data binding: Bind the features property instead, which is an array
        .data(data.features);

    // 3) Enter nodes: When appending them, class them as flow so they keep separated
    flows.enter().append("svg:path")
        .classed("flow", true)
        .attr("d", clip)
        .style("stroke", "black")
        .style("stroke-width", "1px")
        .attr("id", function (d) {
            return d.properties.name.split(' ').join('_')
        });
});

现在它可以工作,但我仍然看不到地球上添加的路径。 path元素肯定会附加到svg元素的DOM中,这可以解决您的初始问题;)

- 更新 -

如评论所示,增加的路径并未跟随地球的运动。这是因为路径被添加到svg但未沿refresh()功能的国家/地区形状更新(添加点4)。

为此,应在refresh()函数中提供对这些路径的选择(它足以在脚本顶部声明var flows),然后为此添加更新在该功能内选择。像这样:

function refresh(duration) {
  (duration ? feature.transition().duration(duration) : feature).attr("d", clip);
  // 4) Added the flows to the paths selection whose d attribute will be updated (only when present)
  flows && (duration ? flows.transition().duration(duration) : flows).attr("d", clip);
}

在这个小提琴上可以看到一个完整的版本:http://jsfiddle.net/oscar_dr/0psy5udk/2/