【问题标题】:d3 - Data loads partiallyd3 - 部分加载数据
【发布时间】:2014-11-14 17:07:19
【问题描述】:

我的工具提示中返回“未定义”的数据字符串有问题,而同一条数据确实会影响我的 svg 的颜色。

目标:我想显示一个叶绿素风格的地图,它显示每个国家的工具提示 a) 国家名称,从 .json 对象加载(工作正常) b) 一些对应于每个国家/地区的值,从 tsv 加载(目前部分工作)

文件结构: 主 .js 文件调用 1 个 topojson 文件(带有国家路径和名称)以及一个 .tsv 文件(带有每个国家的特定区域数据)

使用的资源: 1- MBostock 的叶绿素(见下文注释) 2-贾斯汀帕尔默的d3.tip

玩它

这里有一个Plunker供大家玩玩(由于我使用的world.json很重,可能需要一段时间才能加载)。

---------------

相关代码位

  queue()
.defer(d3.json, "world.json")
.defer(d3.tsv, "winemap.tsv", function setMaptoTotal(d) { rate.set(d.name, +d.total); })
.await(ready);



 var tip = d3.tip()
      .attr('class', 'd3-tip')
       .html(function mylabel(d) { return d.properties.name  + "<table><tr><td><span style='color: #fcf772'> Total area cultivated:  " + d.total  +" ha</span></td></tr><tr><td> <span style='color:#bf2a2a'> Global rank: "+ d.rank + " </span></td></tr></table>";})
      .direction('sw')
      .offset([0, 2]);

var svg = d3.selectAll('body')
    .append('svg')
        .attr('width',width)
        .attr('height',height)
        .call(zoom)
        .call(tip);

// ACTION STARTS HERE // 
function ready(error, world) {
     svg.append("g")
      .attr("class", "counties")
    .selectAll("path")
      .data(topojson.feature(world, world.objects.countries).features)
    .enter().append("path")
 .attr("class", function (d) { return quantize(rate.get(d.properties.name)); })
      .attr("d", path)
      .call(tip)
      .on('mouseover', tip.show)
     .on('mouseout', tip.hide)
     ;

尝试的选项

1- 移动 .call(tip) afterinside ready 函数,该函数通过 queue() 触发数据加载。 >>> 这仍然会在我的工具提示中返回 undefined

2- 使用queue.defer(mylabel(d))。 >>> 屏幕上什么也没有。

3- 考虑到 d3.tsv 的异步特性,我通过了this question。如果我理解得很好,您必须在 d3.tsv 内部和之后引用要调用的函数(设置或不设置全局变量)。因此,我计划在 d3.tsv 内部和之后引用 mylabel(d) 函数。但是我注意到function (d) { return quantize(rate.get(d.properties.name)); }) 没有写在我的d3.tsv 中,但它工作正常。

注意:抱歉,我无法在此阶段发布更多链接,例如到 MBostick 的 chloropleth 或 d3.tip,但它需要更多的声誉 :)

【问题讨论】:

  • 您似乎没有使用包含您要使用的信息的 CSV 数据。它不会自动合并,您需要根据相应国家/地区的名称自行查找其中的信息。

标签: asynchronous d3.js tooltip undefined


【解决方案1】:

万一有人遇到同样的问题,我终于找到了答案。 有两个问题:

1- 数据应首先与数组关联。

首先您需要在ready函数中id与每个数据条目配对

function ready (error, world, data)  {
 var Total= {};
 var Name= {};
 var Rank= {};

 data.forEach(function(d) {
        Total[d.id] = +d.total;
        Name[d.id] = d.name;
        Rank[d.id] = +d.rank;
 });

2- 此方法仅适用于显式引用“id”

命令.data(topojson.feature(world, world.objects.countries).features) 将搜索您要应用转换的每个json 对象的id 属性。在 .json 和 .tsv 文件以及代码中,您的 .tsv 和 .json 之间的桥梁必须是 id

在使用 topoJSON 时不能用任何名称替换 id 的原因是它在 topojson 代码本身中包含一个特定函数(见下文)。

{var r={type:"Feature",id:t.id,properties:t.properties||{},geometry:u(n,t)};return null==t.id&&delete r.id,r}

我通过在我的 .tsv 文件中添加一个列来解决这个问题,该列包含我的 .json 文件中所有 countries 对象的 id 属性。我将此列命名为 id,以便 1- 中描述的配对可以发挥作用。

小心,您希望在 .tsv 上代表 .json 中的所有国家/地区,否则当您将鼠标悬停在 .tsv 上未提及的国家/地区时,“未定义”将再次出现。

最终的工作代码 -

 function ready (error, world, data)  {
     var pairDataWithId= {};
     var pairNameWithId= {};
     var pairRankWithId= {};
    // “d” refers to that data parameter, which in this case is our .csv that (while not necessary) is also named “data.” 
     data.forEach(function(d) {
            pairDataWithId[d.id] = +d.total;
            pairNameWithId[d.id] = d.name;
            pairRankWithId[d.id] = +d.rank;
     });

 // Below my tooltip vars
 var tipin =  function(d) { d3.select(this).transition().duration(300).style('opacity', 1);
 div.transition().duration(300).style('opacity', 1);
 div.text(pairNameWithId[d.id] + " Total Area: "  + pairDataWithId[d.id]+ " Rank: "  + pairRankWithId[d.id])
    .style('left', (d3.event.pageX) + "px")
    .style('top', (d3.event.pageY -30) + "px");
    };
 var tipout =  function() {
     d3.select(this)
     .transition().duration(300).style('opacity', 0.8);
     div.transition().duration(300)
     .style('opacity', 0);
 };

 // Resume

function colorme(d) { return color (pairDataWithId[d.id]);
}

     svg.append('g')
     .attr('class', 'region')
     .selectAll('path')
     .data(topojson.feature(world,world.objects.countries).features)
     .enter()
     .append('path')
     .attr('d', path)
     .style('fill', colorme)
     .style('opacity', 0.8)
     .on ('mouseover', tipin)
     .on('mouseout', tipout);    
 };

注意:我已停止使用 d3.tip 以获得上面包含完整代码的更简单版本。

【讨论】:

    猜你喜欢
    • 2015-11-11
    • 2011-11-23
    • 1970-01-01
    • 1970-01-01
    • 2013-02-05
    • 2010-12-15
    • 1970-01-01
    • 2012-09-13
    • 2018-10-10
    相关资源
    最近更新 更多