【问题标题】:Making a multilayer map with D3使用 D3 制作多层地图
【发布时间】:2014-03-03 21:16:56
【问题描述】:

我正在尝试使用 topjson 加载 D3 地图,并将其加入一个单独的 CSV 文件,其中包含我想用来为地图着色的数据。我可以在多个图层之间切换,但每次都重新绘制地图。我已经搜索了有关如何执行此操作的一些线索,但我似乎无法弄清楚。任何人都可以提供任何帮助吗?

我想将 CSV 和 JSON 数据分开,以防我们想随时动态编辑 CSV。我想一次性将相关课程添加到每个国家/地区,或者在用户在三个按钮之间切换时添加和删除课程。要么对我有用,但我似乎不知道该怎么做。

var width = 945

var height = 550

var svg = d3.select('#content').append('svg').attr('width', width).attr('height', height);

var projection = d3.geo.mercator().scale(175);

var path = d3.geo.path().projection(projection);

var all_data = {};

var tierById = d3.map();

var quantize = d3.scale.quantize()
    .domain([0, 1])
    .range(d3.range(2).map(function(i) { return "tier" + i; }));

queue()
  .defer(d3.json, "data/world.json")
  .defer(d3.csv, "data/wod.csv")
  .await(setUpChoropleth);

function setUpChoropleth(error, json) {

  svg.append("g")
     .attr("class", "countries")
  .selectAll("path")
    .data(topojson.feature(json, json.objects.countries).features)
  .enter().append("svg:path")
    .attr("d", path);

} 

function drawTierI() {
  queue()
      .defer(d3.json, "data/world.json")
      .defer(d3.csv, "data/wod.csv", function(d) { tierById.set(d.id, +d.tier_i); })
      .await(ready);

  function ready(error, json) {
    svg.append("g")
        .attr("class", "countries")
      .selectAll("path")
        .data(topojson.feature(json, json.objects.countries).features)
      .enter().append("path")
        .attr("class", function(d) { return quantize(tierById.get(d.id)); })
        .attr("d", path);

  }
}

function drawTierII() {
  queue()
      .defer(d3.json, "data/world.json")
      .defer(d3.csv, "data/wod.csv", function(d) { tierById.set(d.id, +d.tier_ii); })
      .await(ready);

  function ready(error, json) {
    svg.append("g")
        .attr("class", "countries")
      .selectAll("path")
        .data(topojson.feature(json, json.objects.countries).features)
      .enter().append("path")
        .attr("class", function(d) { return quantize(tierById.get(d.id)); })
        .attr("d", path);

  }
}

function drawTierIIPlus() {
  queue()
      .defer(d3.json, "data/world.json")
      .defer(d3.csv, "data/wod.csv", function(d) { tierById.set(d.id, +d.tier_ii_plus); })
      .await(ready);

  function ready(error, json) {
    svg.append("g")
        .attr("class", "countries")
      .selectAll("path")
        .data(topojson.feature(json, json.objects.countries).features)
      .enter().append("path")
        .attr("class", function(d) { return quantize(tierById.get(d.id)); })
        .attr("d", path);

  }
}

$('button#tier_i').click(function (e) {
  $( "svg" ).empty();
  drawTierI();
});

$('button#tier_ii').click(function (e) {
  $( "svg" ).empty();
  drawTierII();
});

$('button#tier_ii_plus').click(function (e) {
  $( "svg" ).empty();
  drawTierIIPlus();
});

这是我的代码:http://jsfiddle.net/2H7Pm/ 不过,我的 JSON 似乎有一些语法问题。

示例地图确实可以在我的 github 上使用:http://newamericafoundation.github.io/worldofdrones/

感谢您的帮助!

【问题讨论】:

    标签: javascript csv d3.js topojson


    【解决方案1】:

    您只需要选择现有路径,而不是在初始设置 choropleth 后追加新路径,例如

    function drawTierI() {
      csv.forEach(function(d) { tierById.set(d.id, +d.tier_i); });
    
      function ready(error, json) {
        svg.selectAll("path")
            .attr("class", function(d) { return quantize(tierById.get(d.id)); })
            .attr("d", path);
    
      }
    }
    

    对于其他功能也是如此。您也不需要在每一步都重新加载 JSON 和 CSV —— 上面的代码假设您的 CSV 数据存储在变量 csv 中,您将因此填充该变量:

    var csv;
    function setUpChoropleth(error, json, _csv) {
      csv = _csv;
      // rest of setup
    }
    

    那么你可以简单地做

    $('button#tier_i').click(function (e) {
      drawTierI();
    });
    

    无需先清空 SVG 即可更改显示的变量。

    【讨论】:

    • 谢谢!这就说得通了。关于如何纠正切换层时出现的滞后的任何建议?似乎我不应该在每次点击时加载 CSV 和 JSON,但这是我能够从 CSV 调用多个列的唯一方法。
    • 啊,是的,我没有注意到这一点。将更新答案。
    • 谢谢,正如你所描述的那样完美!多亏了你,绝对学到了有关 D3 和 JS 的新知识。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-26
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 1970-01-01
    • 2015-01-13
    相关资源
    最近更新 更多