d3.js图表​​未使用新数据更新

Nyx*_*nyx 4 javascript jquery svg d3.js

d3.js通过获取100个对象的数组来绘制一系列矩形.虽然console.log(data)显示正在检索新数据,但新数据点似乎没有附加任何矩形.

.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 });
}
Run Code Online (Sandbox Code Playgroud)

jsfiddle:http://jsfiddle.net/BU8cA/

Ame*_*aBR 17

更新方法的问题在于它只处理新元素,并且不更新现有元素以匹配其新数据.使用enter()选择创建新矩形后,必须返回完整选择(新的和更改的矩形)以设置要更改的属性.

最简单的方法是将选择存储在应用数据函数但在调用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
Run Code Online (Sandbox Code Playgroud)

这应该得到正确的数据,但你仍然有一个布局问题(在小提琴上,无论如何),因为你的y值没有正确设置.y值是矩形顶部的位置,因此如果您希望条形看起来像是全部位于同一条线上,则需要根据条形的高度进行调整.Mike Bostock的教程和演示:http://bost.ocks.org/mike/bar/3/


D3版本4+的更新

附加到"输入"选项的元素不再自动添加到主(更新)选择中.您现在需要通过调用merge"enter"选项上的方法显式创建"合并"选择:

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; });
Run Code Online (Sandbox Code Playgroud)