我想使用两个不同的数据源将g
元素添加到svg
。但是,我最终将第二个数据源绑定到现有的g
元素,而不是创建新的g
元素。
这是一个例子
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<div id="body"></div>
<script type="text/javascript">
var canvas_w = 1280 - 80,
canvas_h = 800 - 180;
var svg = d3.select("#body").append("div")
.append("svg:svg")
.attr("width", canvas_w)
.attr("height", canvas_h)
var category_cells = svg.selectAll("g")
.data([0, 1, 2])
.enter().append("g")
.attr("class", "category")
.attr("transform", function(d) {console.log(d); return "translate(" + d*100 + ", 0)"; });
category_cells.append("rect")
.attr("y", 0)
.attr("x", 0)
.attr("width", 50)
.attr("height", 50)
.style("fill", "blue");
var cell = svg.selectAll("g")
.data([3, 4, 5])
.enter().append("g")
.attr("class", "cell")
.attr("transform", function(d) {console.log(d); return "translate(" + d*100 + ", 0)"; });
cell.append("rect")
.attr("y", 0)
.attr("x", 0)
.attr("width", 50)
.attr("height", 50)
.style("fill", "black");
</script>
</body>
</html>
此脚本显示三个类g.category
框,而不是六个框,其中三个类g.category
和三个类g.cell
。它也只记录&#34; 1 2 3&#34;显示从未输入enter
g.cell
语句之后的转换。另外,如果我通过添加
svg.selectAll("g.category")
.attr("transform", function(d) {console.log(d); return "translate(" + d*100 + ", 0)"; });
g.category
转换会更改以反映数据[3 4 5]
。很明显,新数据会覆盖g.category
数据,而不是分配给新的g.cell
元素,但如何防止这种情况发生?
tutorials和documentation我已经阅读了关于将数据绑定到尚不存在的元素的讨论,但是他们没有处理相同类型的元素的情况存在。
我的猜测是解决方案位于更新模式的某个位置。从文档中有几个地方我可以更改各种元素的属性。
var update_sel = svg.selectAll("g").data(data)
update_sel.attr(/* operate on old elements only */)
update_sel.enter().append("g").attr(/* operate on new elements only */)
update_sel.attr(/* operate on old and new elements */)
update_sel.exit().remove() /* complete the enter-update-exit pattern */
但它并没有解释data
调用如何更改旧元素的数据绑定。
Using selectAll() to create new elements while preserving existing elements询问如何在没有嵌套元素的情况下使用selectAll
,这不是我面临的问题。
答案 0 :(得分:1)
问题是默认情况下,D3使用索引来匹配数据。也就是说,第一个数据匹配选择中的第一个DOM元素,第二个数据匹配第二个,依此类推。在您的代码中,您在两种情况下都选择g
元素,因此第二次运行此代码时,数据会反弹到元素中,并且您得到的结果是您不期望的。< / p>
解决方案很简单 - 只需按照您指定的类选择元素,即在创建元素时使用.selectAll("g.category")
和.selectAll("g.class")
。或者,您可以向.data()
提供一个关键功能,告诉D3如何匹配元素和数据以防止重新绑定,但恕我直言,这将不那么直观。