简体   繁体   中英

How to programmatically add properties to topojson file at runtime?

I'm trying to add additional properties to a topojson at runtime. I've looked at the Choropleth example but I don't think that one manipulates the original json file.

What's the best way to do this?

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":[ ... ]
              } ... 
    }

The merging array will look something like this:

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

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

No, he doesn't. In the example you linked, Mike Bostock creates a map...

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

... and after that he uses that map:

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

That approach, as you can see, doesn't change the topoJSON. Besides that, it's faster and more elegant.

However, if you want to add properties to the topoJSON, that can be easily done.

First, nest your d3.json and your d3.csv (or any other function you use to get the data):

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

Then, use two nested for loops to add the properties (not the faster solution). In this demo, I'm hardcoding the topoJSON and using a <pre> to load the CSV because, in a Stack snippet, I cannot upload the real files.

Check it, the original topoJSON object has no count property, but the result shown in the console.log has:

 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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM