2

我正在从一个包含 1955 年到 2012 年选定国家的 GDP 的谷歌电子表格中加载数据。我想从这里绘制一个树形图。到目前为止,一切都很好。

我已经通过外部链接加载数据并格式化为 d3 可以处理的对象,然后让布局在屏幕上绘制——一切都很好。我以http://bl.ocks.org/mbostock/4063582上的 Mike Bostock 教程为基础。

当我尝试从 1955 年到 2010 年的一组数据转换时,问题就出现了。我确信我用来生成树形图布局的函数正在工作,因为初始显示是正确的。我将日期传递给它,它会创建树形图结构。

但是,当我触发更改时,似乎会发生过渡,并且各个方块会改变大小。但是当我检查它们时,我意识到它们都是错误的,而且我似乎将新的价值观映射到了错误的国家。

新结构在视觉上看起来是正确的,但所有的名称都是错误的。所以我得到了像塞浦路斯在 2012 年拥有最大 GDP 之类的东西。就好像我有一个按字母顺序排列的列表,其中有另一组按数量顺序排列的值,而不是说美国正在映射的新值旧值。

在这里转圈,因为我对 d3 仍然很陌生,所以所有的帮助都非常感激。

代码如下所示:

/*global app:true JST:true d3:true*/

(function (window, $) {

'use strict';

var menuItems = [];
var menuType='measure';
var checboxItems= ['advanced','emerging'];
var ddID = '0';
var model=[];
var yearValue="2012"
var group="gdp";
var treeStruc={
name:[],
children:[]
}

var margin = {top: 25, right: 5, bottom: 5, left: 5},
width = 965 - margin.left - margin.right,
height = 650 - margin.top - margin.bottom;

var color = d3.scale.category10();



app.spreadsheet.get(function (data) {
// TODO: process the data
menuItems = data.measures
//console.log(data);
//console.log('menuItems', menuItems);
//crete dropdown and use toggle to swich display on and off
$('#dropDown').click(function () {
  $('ul.ddMenuList').toggle();
});
//populate the dropdown menu
for (var k = 0; k <menuItems.length; k++) {
  $('#ddList').append('<li id="dd_' + k + '"><a href="#">'+menuItems[k].menulist     +'</li>');
};
//add functionality to dropDown menu
$('#ddList li').bind('click', function () {
  ddID = this.id.split('_')[1];
      var text = $(this).text();
  //console.log ("ID=",ddID);
  //console.log (text, "Measure=",menuItems[ddID].type);
  $('#ddTitle').empty();
  $('#ddTitle').append(text);
  createCheckboxes()
});

function createCheckboxes() {
//decide which check boxes to populate
if (menuItems[ddID].type==="measure") {
  group=menuItems[ddID].type
  checboxItems=[];
  $.each(menuItems, function (i) {
    if (menuItems[i].type==="group"){
      checboxItems.push (menuItems[i].checkbox);
    }
    //console.log (checboxItems);
  });
}
    else {
  group=menuItems[ddID].type
  checboxItems=[];
  $.each(menuItems, function (i) {
    if (menuItems[i].type==="measure"){
      checboxItems.push (menuItems[i].checkbox);
    }
    //console.log (checboxItems);
  });
}
//Populate the check boxes
console.log ("Populating check boxes");
$('#cbHolder').empty();
$('#cbHolder').append('<form>');
    $.each(checboxItems, function (i) {
  $('#cbHolder').append('<input type="checkbox" id="cb_'+i+'">'+checboxItems[i]);
  $('#cbHolder').append('</form>');
  //console.log ("checkboxItems",checboxItems[i]);
});
changed3 ()

}

//creates an object containing just the advanced countries
treeStruc={name:[],children:[]};
console.log ("group=",group);
$.each(checboxItems, function (k) {
  console.log("Parent",checboxItems[k])
  model=jQuery.grep(data.stats,function(e,i){return e[checboxItems[k]];});
  console.log('model', model);
  treeStruc.children.push({"name":checboxItems[k],"children":[]});
  //Construct the children of 1 big group to be completed to be updated for each sheet
  $.each(model, function (i) {
  treeStruc.children[k].children.push({'name':model[i].countryname,'size':model[i]    [group]});
  });
});



console.log('treeStruc', treeStruc)
Handlebars.createOptionsHelper(data.options);
drawd3 ();
});


function generateTreemapLayout(filter){
  return d3.layout.treemap()
    .size([width, height])
    .sticky(true)
    .value(function(d) { 
      if(d.size[filter] < 0){
        return 0;
      }
  return d.size[filter]; 
    });
  }

function drawd3() {
  console.log ("function drawd3");
  var treemap = generateTreemapLayout('y'+yearValue)



  var div = d3.select("#d3Object").append("div")
    .style("position", "relative")
    .style("width", (width + margin.left + margin.right) + "px")
    .style("height", (height + margin.top + margin.bottom) + "px")
    .style("left", margin.left + "px")
    .style("top", margin.top + "px");

    var node = div.datum(treeStruc).selectAll(".node")
      .data(treemap.nodes)
    .enter().append("div")
      .attr("class", "node")
      .call(position)
      .attr("id",function(d){
        return d.name;
      })
      .style("background", function(d) { return d.children ? color(d.name) : null; })
      .text(function(d) { return d.children ? null : d.name; });

    };
    function position() {
      this.style("left", function(d) { return d.x + "px"; })
          .style("top", function(d) { return d.y + "px"; })
          .style("width", function(d) { return Math.max(0, d.dx - 1) + "px"; })
          .style("height", function(d) { return Math.max(0, d.dy - 1) + "px"; });
}


function changed3() {
    console.log ("function changed3");
    //make a new treemap layout
    var treemap = generateTreemapLayout('y'+1955);
    console.log('treeStruc',treeStruc);
    //redraw the treemap using transition instead of enter  


    var node = d3.select("#d3Object")
    .datum(treeStruc).selectAll(".node")
    .data(treemap.nodes)
    .transition()
    .duration(1500)
    .call(position)

  }

}(this, jQuery));
4

1 回答 1

3

非常感谢我的同事 Tom Pearson。问题在于数据绑定到页面上的项目的位置。当您重新绘制树形图时,因为数据没有绑定到具有唯一标识符(如对象名称)的 div,它会将数据重新映射到列表的第一项,因为它在哪里。这意味着像中国这样的东西会得到比利时的信息。简单的解决方案如下

.data(treemap.nodes)

利用

 .data(treemap.nodes,function(d){
  return d.name;
})

这是原始 drawd3 函数中 this 的两个实例,它们在 changed3 函数中。希望能帮助任何遇到类似问题的人

于 2013-10-11T10:41:46.607 回答