如何在运行时以编程方式将属性添加到 topojson 文件?

How to programmatically add properties to topojson file at runtime?

我正在尝试在运行时向拓扑添加额外的属性json。我看过 Choropleth 示例,但我不认为有人会操纵原始 json 文件。

最好的方法是什么?

JSON:

   { "type":"Topology",
     "objects":{  
        "countries":{  
           "bbox":[  ...  ],
           "type":"GeometryCollection",
           "geometries":[  
              {  
                 "type":"Polygon",
                 "properties":{  
                    "name":"Afghanistan",
                    "count": 30 // <------- Property I want to add.
                 },
                 "id":"AFG",
                 "arcs":[ ... ]
              },
              {  
                 "type":"MultiPolygon",
                 "properties":{  
                    "name":"Angola",
                    "count": 50 // <------- Property I want to add.
                 },
                 "id":"AGO",
                 "arcs":[ ... ]
              } ... 
    }

合并数组看起来像这样:

[{ "Angola" : 50 }, { "Afganistan" : 30 }, ... ]

I've looked at the Choropleth example but I don't think that one manipulates the original json file.

不,他没有。在您链接的示例中,Mike Bostock 创建了一个地图...

var unemployment = d3.map();
unemployment.set(d.id, +d.rate);

...然后他使用了那张地图:

.attr("fill", function(d) { return color(d.rate = unemployment.get(d.id)); })

如您所见,该方法不会更改 topoJSON。除此之外,它更快更优雅。

但是,如果您想向 topoJSON 添加属性,那可以很容易地完成。

首先,嵌套您的 d3.jsond3.csv(或您用来获取数据的任何其他函数):

d3.csv("mycsv.csv", function(data) {
    d3.json("mytopojson.json", function(json) {
        //code here
    });
});

然后,使用两个嵌套的 for 循环来添加属性(不是更快的解决方案)。在此演示中,我对 topoJSON 进行硬编码并使用 <pre> 加载 CSV,因为在 Stack 片段中,我无法上传真实文件。

检查一下,原来的topoJSON对象没有count属性,但是console.log中显示的结果有:

var topoJSON = {
    "type": "Topology",
    "objects": {
        "countries": {
            "type": "GeometryCollection",
            "geometries": [{
                "type": "Polygon",
                "properties": {
                    "name": "Afghanistan"
                },
                "id": "AFG"
            }, {
                "type": "MultiPolygon",
                "properties": {
                    "name": "Angola"
                },
                "id": "AGO",
            }]
        }
    }
};

var csv = d3.csvParse(d3.select("#csv").text());

var geometries = topoJSON.objects.countries.geometries;

for (var i = 0; i < csv.length; i++) {
    for (var j = 0; j < geometries.length; j++) {
        if (csv[i].country == geometries[j].id) {
            geometries[j].properties.count = csv[i].count;
        }
    }
}

console.log(topoJSON);
pre{
  display:none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<pre id="csv">country,count
AGO,50
AFG,30</pre>