使用完全不同的数据重新绘制图表

时间:2015-09-14 21:47:12

标签: javascript d3.js svg

所以这就是问题,我正在努力使这个例子工作http://bl.ocks.org/mbostock/1093130所以“更新”功能(每当我按下DOM时按钮都会调用)重新绘制图形一个全新的不同数据集......我对这个例子做了一些修改来试试这个。因此,假设我想用不同的json随机提供图形,这些json的名称存储在数组中:

var array = ["graph.json","graph2.json"];    
function reload() {
    var rnd = Math.floor(Math.random()*2);
    d3.json(array[rnd], function(error, json) {
        if (error) throw error;

        root = json;
    update();
});    
}

问题是,当重新绘制图形时,它总是存在某种错误,比如属于以前数据集的某个节点,或类似的东西......所以首先我尝试从容器中删除元素在调用update()之前我已经在SO中看到过的所有可能的方式都没有用,所以(如果我错了请纠正我)我读了一下,发现data()函数使用了一些一种连接方法,所以你可以随着数据中注册的每一个变化或类似的东西不断更新图形,这很酷,但显然不是我需要的。所以我尝试用datum()更改数据(),因为如果你不想动态更新你的布局,我会读到最后应该使用的那个,并且我删除了enter()和exit()调用,因为我读到它们是不需要因为基准不计算这样的功能。代码编译但不起作用,没有任何东西被绘制。这是我得到的(我只放了update()函数,因为其他一切都没有改变):

function update() {
var nodes = flatten(root),
    links = d3.layout.tree().links(nodes);

  // Restart the force layout.
force
  .nodes(nodes)
  .links(links)
  .start();

// Update links.
link = link.datum(links, function(d) { return d.target.id; });

link.insert("line", ".node")
  .attr("class", "link");

// Update nodes.
node = node.datum(nodes, function(d) { return d.id; });

var nodeEnter = node.append("g")
  .attr("class", "node")
  .on("click", click)
  .call(force.drag);

nodeEnter.append("circle")
  .attr("r", function(d) { return Math.sqrt(d.size) / 10 || 4.5; });

nodeEnter.append("text")
  .attr("dy", ".35em")
  .text(function(d) { return d.name; });

node.select("circle")
  .style("fill", color);

}

提前感谢您的帮助。

enter image description here

正如您在上图所示,显示的数据与数据集不对应,它应显示“Mike”,“Mike Jr.”,“Paul”等名称......正如我之前指出的那样您尝试收回/折叠单击根节点的节点时,会更正某些数据(而不是根节点上的数据)。

以下是应显示的数据:

//Second graph
{
 "name": "Mike",
 "children": [
  {
   "name": "Mike Jr.",
   "children": [
    {
     "name": "Paul",
     "children": [      
      {"name": "Peter", "size": 743}
     ]
    }
   ]
  }
 ]
}

1 个答案:

答案 0 :(得分:1)

因此,您可能会遗漏D3enterupdateexit模式的一些基础知识。来自Mike Bostock的Here's an article解释了这个主题,我在下面的帖子中添加了一张图片:

enter image description here

基本思路是,当您想要修改数据时,需要再次加入数据:

var circles= d3.selectAll("circle").data(nodes, function(d) { return d.id; });

然后使用相关函数来确定更改的内容。引擎盖下的D3会跟踪您的数据和HTML元素,并确定需要更改的内容。因此你可以这样做:

circles.enter().append("circle"); // Add circles for new items
circles.exit().remove();          // Remove old circles from the DOM as there's no data for them anymore

请注意,一旦调用enter(),这些数据项就已移至update部分 - 即已在DOM中有表示的数据点。这意味着您现在可以:

circles.attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; })

但最后我应该注意,将key函数传递到.datum().data()也很重要。我注意到你已经有了,你几乎肯定需要把它留在那里。