繁体   English   中英

访问topojson对象以更改d3.js中的地图国家/地区属性

[英]Access topojson object to change map country properties in d3.js

我正在构建一个Web应用程序,以显示世界各国之间的不同趋势和统计数据。 使用d3,我可以加载topojson文件并投影世界地图。

  var countryStatistics = [];
  var pathList = [];

function visualize(){

var margin = {top: 100, left: 100, right: 100, bottom:100},
    height = 800 - margin.top - margin.bottom, 
    width = 1200 - margin.left - margin.right;

 //create svg
var svg = d3.select("#map")
      .append("svg")
      .attr("height", height + margin.top + margin.bottom)
      .attr("width", width + margin.left + margin.right)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  //load topojson file
d3.queue()
  .defer(d3.json, "world110m.json")
  .await(ready)  

var projection = d3.geoMercator()
  .translate([ width / 2, height / 2 ])
  .scale(180)

  //pass path lines to projection
var path = d3.geoPath()
.projection(projection);

function ready (error, data){
  console.log(data);

    //we pull the countries data out of the loaded json object
  countries = topojson.feature(data, data.objects.countries).features

    //select the country data, draw the lines, call mouseover event to change fill color
  svg.selectAll(".country")
    .data(countries)
    .enter().append("path")
    .attr("class", "country")
    .attr("d", path)
    .on('mouseover', function(d) {
      d3.select(this).classed("hovered", true)
        //this function matches the id property in topojson country, to an id in (see below)
      let country = matchPath(this.__data__.id);
      console.log(country)
    })
    .on('mouseout', function(d) {
      d3.select(this).classed("hovered", false)
    })
      //here I push the country data into a global array just to have access and experimentalism. 
    for (var i = 0; i < countries.length; i++) {
      pathList.push(countries[i]);
    } 
  }
};

matchPath()函数用于允许我将路径数据与countryStatistics匹配,以便将鼠标悬停在某个国家时显示。

function matchPath(pathId){
    //to see id property of country currently being hovered over
  console.log("pathID:" + pathId)
    //loop through all countryStatistics and return the country with matching id number
  for(var i = 0; i < countryStatistics.length; i++){
    if(pathId == countryStatistics[i].idTopo){
      return countryStatistics[i];
    }
  }
}

问题:这有效,但仅在一个方向上有效。 我可以从每个topojson路径获取统计数据...但是我无法根据数据访问和处理单个路径。

我想做的是拥有一个按钮,该按钮可以从countryStatistics中选择某个属性,并建立域/范围比例并根据数据值设置颜色渐变。 我坚持的步骤是获取统计数据和路径数据接口。

我看到了两个潜在的解决方案,

1:有一种方法可以在渲染过程中将拓扑路径数据连接到统计数据,我可以调用一个函数来重绘sgv ...

2:我建立了一个包含所有路径数据和统计数据的新对象。 在这种情况下,我可以只提取topojson.objects.countries数据而忽略其余数据吗?

我应该如何实现呢? 任何指针,下一步将不胜感激。

(我在这个项目上的位置... http://conspiracytime.com/globeApp

TopoJSON是一个非常强大的工具。 它具有自己的CLI( 命令行界面 )以生成自己的TopoJSON文件。

该CLI允许您使用拓扑和要合并的数据创建唯一文件。

即使在v3.0.2中, 第一个versión在我看来仍然很清楚。 这是一个示例,说明如何通过公共id属性将csv文件与json合并。

# Simplified versión from https://bl.ocks.org/luissevillano/c7690adccf39bafe583f72b044e407e8
# note is using TopoJSON CLI v1
topojson \
  -e data.csv \
  --id-property CUSEC,cod \
  -p population=+t1_1,area=+Shape_area \ 
  -o cv.json \
  -- cv/shapes/census.json

有一个data.csv与文件cod栏和census.json文件使用指定属性CUSEC -使用--id-property您可以指定在合并中使用哪些属性。 -使用property -p您可以即时创建新属性。

这是一种可靠的解决方案,其中您将一个唯一文件(带有一个唯一请求 )与整个数据一起使用。 最好的情况并不总是可能的,因此下一个解决方案可能是另一个。

回到JavaScript ,您可以通过以下常用方式创建一个可通过属性访问的新变量。 数据格式如下:

// countryStatistics
{
  "idTopo": "004",
  "country": "Afghanistan",
  "countryCode": "afg",
  // ..
},

和您的TopoJSON文件的结构:

{"type":"Polygon","arcs":[[0,1,2,3,4,5]],"id":"004"},
{"type":"MultiPolygon","arcs":[[[6,7,8,9]],[[10,11,12]]],"id":"024"} // ...



此类情况的常见解决方案是创建一个可由idTopo访问的Array变量:

var dataById = [];
countryStatistics.forEach(function(d) {
    dataById[d.idTopo] = d;
});

然后,该变量将具有下一个结构:

[
    004:{
      "idTopo": "004",
      "country": "Afghanistan",
      "countryCode": "afg",
      //...
  },
    008: {
      //...
    }
]

在这里,您可以通过其idTopo属性访问属性,如下所示:

dataById['004'] // {"idTopo":"004","country":"Afghanistan","countryCode":"afg" ...}

您可以决定遍历Topo数据并将这些属性添加到每个功能中:

var countries = topojson
  .feature(data, data.objects.countries)
  .features.map(function(d) {
    d.properties = dataById[d.id];
    return d
  });

或者在需要时使用此数组

// ...
.on("mouseover", function(d) {
  d3.select(this).classed("hovered", true);
  console.log(dataById[d.id]);
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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