javascript - 使用 D3 制作直方图动画

标签 javascript d3.js histogram

我在这个 jsFiddle here 上有一些代码为称为“值”的数据数组生成直方图。这一切都很好。

当我想用一个名为“newData”的新数据数组更新这个直方图时,事情就出了问题。我试图遵守 enter()update()exit() D3 策略(我显然对此非常陌生) 。动画确实发生了,但正如您通过 fiddle 看到的那样,它只是将所有内容压缩到右上角。有人可以指出我在这段代码(更新)中做错了什么吗?

//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 上。谢谢!

最佳答案

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

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

您的方向是正确的,但您需要区分数据更改时需要更新的内容和数据更改时不应更新/声明的内容。您只需声明 d3 模式(绑定(bind)、添加、更新、删除)一次...它将适用于更新的数据集。

因此,请在 makeHist(values) 函数外部声明尽可能多的内容,并且仅在函数内部包含需要更改数据的代码(这包括修改先前声明的比例的域和范围)。然后,单击函数只需使用新数据再次调用 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);
});

这是一个大部分工作的更新 fiddle ,但需要一些清理:

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

剧透警告:两个数据集并没有那么不同

关于javascript - 使用 D3 制作直方图动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24209558/

相关文章:

javascript - 使用复选框和 javascript 更改 CSS 值

JavaScript:如何异步下载JS?

javascript - 如何创建在 y 轴上具有唯一计数、在 x 轴上具有类别的基本条形图?

javascript - 将 React 升级到 0.13.2 会导致 : "Uncaught TypeError: Cannot read property ' _currentElement' of null"

Scala简单直方图

python - 对于直方图,如何保留所有指定的 bin-ticks 沿 x 轴并仅显示指定的 bin-ticks 的数字标签?

javascript - 如何在获取错误中包含已解析的响应和原始响应 header

javascript - 单击按钮时元素未隐藏

javascript - 隐藏多个json d3组

r - 在 R 中将直方图与密度图相结合