我在这个 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/