用D3动画直方图

时间:2014-06-13 16:02:23

标签: javascript d3.js histogram

我在这个jsFiddle here上有一些代码,它为数据数组生成一个名为" values"的直方图。这一切都很好。

当我想用一个名为" newData"的新数据数组更新此直方图时,出现问题。我正在努力遵守enter()update()exit() D3策略(我显然是非常新的)。动画确实会发生,但正如你可以通过小提琴看到的那样,它只是将所有内容都放到了右上角。有人能指出我在代码的这一部分(更新)中做错了吗?

//Animations
d3.select('#new')
  .on('click', function(d,i) {
  var newHist = d3.layout.histogram().bins(x.ticks(bins))(newData);

  var rect = svg.selectAll(".bar")
   .data(values, function(d) { return d; });

  // enter
  rect.enter().insert("g", "g")
    .attr("class", "bar")
    .attr("transform", function(d) { return "translate(" + x(d) + "," + y(d) + ")"; });

  rect.enter().append("rect")
    .attr("x", 1)
    .attr("width", w)
    .attr("height", function(d) { return y(d); });
  rect.enter().append("text")
    .attr("dy", ".75em")
    .attr("y", 6)
    .attr("x", x(histogram[0].dx) / 2)
    .attr("text-anchor", "middle")
    .text(function(d) { return formatCount(d); });

  // update    
  svg.selectAll('.bar')
    .data(newHist)
    .transition()
    .duration(3000)
    .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });
  svg.selectAll("rect")
    .data(newHist)
    .transition()
    .duration(3000)
    .attr("height", function(d) { return height - y(d.y); });
  svg.selectAll("text")
    .data(newHist)
    .transition()
    .duration(3000)
    .text(function(d) { return formatCount(d.y); });
    // exit
    rect.exit()
    .remove();
});

整个代码都在上面链接的JSFiddle上。谢谢!

1 个答案:

答案 0 :(得分:1)

看看上面的代码和小提琴,我突然想到了一些事情:

  • (第85行)您仍在绑定原始数据
  • (第105,115行)您正在多次绑定数据
  • (第99行)您仍在引用原始直方图变量,而不使用新数据进行更新
  • 您正在为一组(更改)数据声明多个绑定/添加/更新/删除模式

您处于正确的轨道上,但您需要区分数据更改时需要更新的内容以及数据更改时不应更新/声明的内容。您只需要声明d3模式(绑定,添加,更新,删除)一次......它将适用于更新的数据集。

因此,尽可能多地在makeHist(values)函数之外声明,并且只需要在函数内部需要更改数据的代码(这包括修改先前声明的缩放的域和范围)。然后,on click函数可以使用新数据再次调用makeHist函数。

这是一个粗略的概述:

// generate data

// declare everything that can be static
// (add svg to dom, declare axes, etc)

// function that handles everything that new data should modify
function makeHist(values) {

    // modify domains of axes, create histogram

    // bind data
    var rect = svg.selectAll('rect')
       .data(histogram);

    // add new elements
    rect.enter().append('rect');

    // update existing elements
    rect.transition()
        .duration(3000)
        .attr('transform', '...');

    // remove old elements
    rect.exit().remove();

}

// generate initial histogram
makeHist(initialValues);

// handle on click event
d3.select('#new')
  .on('click', function() {
    makeHist(newData);
});

这是一个大多数工作更新的小提琴,它需要一点点清理,但是:

http://jsfiddle.net/spanndemic/rf4cw/

扰流警报:两个数据集并非完全不同