我以为我理解D3进入/更新/退出,但我在实现示例时遇到问题。 http://jsfiddle.net/eamonnmag/47TtN/中的代码说明了我正在做的事情。如您所见,每隔5秒钟,我会增加一个项目的评级,然后再次更新显示。这在某种程度上起作用。问题是只更新已更改的内容 - 在这种情况下,D3正在更新所有内容。进入和退出方法,在控制台输出中显示没有任何改变,这使我认为它将每个数组视为一个全新的实例。
我对selectAll()和data()调用的理解是,它会将所有数据“绑定”到幕后某个地方名为“巧克力”的地图,然后做一些逻辑来检测不同的内容。
var chocolate = svg.selectAll("chocolates").data(data);
在这种情况下,这不是正在发生的事情。这是更新代码。任何指向我错过的内容都非常感谢!
function update(data){
var chocolate = svg.selectAll("chocolates").data(data);
var chocolateEnter = chocolate.enter().append("g").attr("class", "node");
chocolateEnter.append("circle")
.attr("r", 5)
.attr("class","dot")
.attr("cx", function(d) {return x(d.price)})
.attr("cy", function(d) {
//put the item off screen, to the bottom. The data item will slide up.
return height+100;})
.style("fill", function(d){ return colors(d.manufacturer); });
chocolateEnter
.append("text")
.text(function(d) {
return d.name;})
.attr("x", function(d) {return x(d.price) -10})
.attr("y", function(d){return y(d.rating+step)-10});
chocolateEnter.on("mouseover", function(d) {
d3.select(this).style("opacity", 1);
}).on("mouseout", function(d) {
d3.select(this).style("opacity", .7);
})
chocolate.selectAll('circle')
.transition().duration(500)
.attr('cy', function(d) {return y(d.rating+step)});
var chocolateExit = chocolate.exit().remove();
chocolateExit.selectAll('circle')
.attr('r', 0);
}
setInterval(function() {
chocolates[3].rating = Math.min(chocolates[3].rating+1, 5);
update(chocolates);
}, 5000);
答案 0 :(得分:1)
你为什么要做svg.selectAll("chocolates")
?您的DOM中没有名为chocolates
的HTML元素。
您需要将其更改为svg.selectAll(".node")
。这将解决问题。
答案 1 :(得分:1)
您的代码中存在一些问题。首先,默认情况下,检测不同内容的逻辑是使用项目的索引。也就是说,第一个数据项与第一个DOM元素匹配,依此类推。这适用于您的情况,但如果您传入部分数据,则会中断。我建议使用.data()
的第二个参数告诉它如何匹配:
var chocolate = svg.selectAll("g.node").data(data, function(d) { return d.name; });
其次,正如另一张海报所指出的那样,选择“巧克力”将不会选择任何东西,因为没有这样的DOM元素。只需选择实际的元素即可。
最后,由于您要为数据项添加g
元素,因此您也可以使用它们。我的意思是,目前,您正在单独处理圆圈和文本,并且必须更新它们。但是,您可以将所有内容放在g
元素下面。然后你必须只更新那些,这简化了你的代码。
我在您修改过的小提琴here中进行了以上所有更改。