如何在运行时以编程方式将属性添加到 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.json
和 d3.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>
我正在尝试在运行时向拓扑添加额外的属性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.json
和 d3.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>