2013-12-20 94 views
2

使用d3.js通过获取100个对象的数组绘制一系列矩形。尽管console.log(data)显示正在检索新数据,但新数据点似乎没有附加任何矩形。d3.js图表​​未更新新数据

.enter().append()使用不正确?

function init() { 
    var width = 800, 
     height = 400, 
     margin = 50; 

    chart = d3.select('#chart') 
       .append('svg:svg') 
       .attr('width', width) 
       .attr('height', height); 
} 

function do_update() { 
    data = fetch_latest_top100(); 
    console.log(data) 

    chart.selectAll('rect') 
     .data(data) 
     .enter() 
     .append('svg:rect') 
     .attr('x', function(d) { return x(d.x); }) 
     .attr('y', function(d) { return y(d.y); }) 
     .attr('height', function(d) { return d.value; }) 
     .attr('width', function(d) { return 3 }); 
} 

的jsfiddlehttp://jsfiddle.net/BU8cA/

+0

这将是更好,如果你有一个小提琴(http://jsfiddle.net/)或plunkr http://plnkr.co/edit/?p=catalogue这将有助于看到问题生活 –

+0

我不知道这是一个复制/粘贴的问题,但你错过了一个“)”之后y(dy在y attr,这可能是错误 – tomtomtom

+0

@tomtomtom复制粘贴问题,更正了错字,谢谢! – Nyxynyx

回答

11

与更新方法的问题是,它只能处理新的元素,并且不更新现有的元素,以满足他们新的数据。使用enter()选择创建新矩形后,必须返回完整选择(新的和变化的矩形)以设置要更改的属性。

要做到这一点,最简单的方法是选择存储在一个变量在您应用了数据功能点,但在打电话之前的输入法,如:

var rects = chart.selectAll('rect') 
     .data(data); 

    rects.enter() 
     .append('svg:rect') 
     .attr('width', function(d) { return 3 }); 
     // since the width is constant, you only need to set it once 

    rects.exit().remove(); //if the number of data points might shrink 

    rects.attr('x', function(d) { return x(d.x); }) 
     .attr('y', function(d) { return y(d.y); }) 
     .attr('height', function(d) { return d.value; }); 
    //note that this now includes the rectangles created with enter() 
    //as well as the old ones you are resizing/repositioning 

这应该得到正确的数据,但你仍然有一个布局问题(无论如何,在小提琴),因为你的y值没有被正确设置。 y值是矩形顶部的位置,所以如果您想要看起来像是全部坐在同一条线上的酒吧,则需要根据酒吧的高度进行调整。迈克·博斯托克的教程和演示在这里:http://bost.ocks.org/mike/bar/3/


更新版本的D3 4+

元素附加到“输入”选择不再自动添加到主(更新)选择。现在,您需要明确地创建一个“合并”选项,通过调用“输入”选择merge方法:

var rects = chart.selectAll('rect') 
    .data(data); 

rects.exit().remove(); //if the number of data points might shrink 

rects.enter() 
    .append('svg:rect') 
    .attr('width', function(d) { return 3 }) // since the width is constant, you only need to set it once 

    .merge(rects) 
      //merge the newly added elements into the main selection 
      //of existing elements to update 
    .attr('x', function(d) { return x(d.x); }) 
    .attr('y', function(d) { return y(d.y); }) 
    .attr('height', function(d) { return d.value; }); 
+0

这个答案仍然有效吗?如果在调用rects.enter()。append()之后调用rects.nodes(),我仍然会返回一个空数组。如果上面的声明“现在包含使用enter()创建的矩形”是真实的,那么我是否应该看到一个已填充的数组,而不是在调用.nodes()时的空数组? – MattEvansDev

+1

@mevans您是否在使用D3 v4?它改变了合并的工作方式,请参阅[Mike Bostock关于更改背后推理的概述](https://medium.com/@mbostock/what-makes-software-good-943557f8a488)。您现在需要显式调用'selection.merge()'来合并输入和更新选择。 – AmeliaBR

+0

是的 - 我正在使用D3 v4。 .merge()的引入和输入/更新(现在的功能与网络上的大多数示例相反)的变化令人生气。非常感谢澄清。 – MattEvansDev