如何解决d3.js-selectAll的作用是返回不存在的元素
使用d3.js,我有以下简单的代码,可以基于数据集添加矩形。
我没有svg或rect,所以我通过.append()将其附加。
let dataset = [ 1,2,3,4,5 ]
let svg = d3.select("body")
.append("svg")
.attr /* width,height */
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr /* x,y,width,height,etc */
这很好用。
我的问题是selectAll("rect")
。
为什么需要这个? 如果我按如下所示将其删除,则rect元素将位于body元素之外。
但是svg的追加不是应该追加到引用元素的末尾吗? (在这种情况下是svg?)
svg.data(dataset)
.enter()
.append("rect")
.attr /* x,etc */
我知道selectAll返回引用。
如果该元素不存在,是否返回特殊引用?
解决方法
D3使用称为data join的更新范例。它针对数据的增量更新进行了优化,以适应图表的使用。
要使用数据联接,请对“选择”进行操作。不用选择就代表了您想要做什么,而是代表了您希望数据如何转换。
let dataset = [ {name: "a",value: 1},{name: "b",value: 2},{name: "c",value: 3} ]
let svg = d3.select("body")
.append("svg")
const selection = svg.selectAll("rect")
.data(dataset,d => d.name) // data join,each "rect" will correspond to an data
// second argument is a key function to uniquely identify each data
selection
.enter()
.append("rect")
/* attr: x,y,height,width */
选择代表数据联接。在这里,您告诉D3您正在选择。目前,DOM中什么都没有,所以我们得到了一个空的选择。
定义选项时:
- DOM没有“矩形”节点
- 但是有数据
以另一种方式看待它:
data
data &nodes nodes
+-----+
+--------------------+
| | | |
| a:1 | | |
| b:2 | | |
| c:3 | | |
| | | |
+--------------------+
+-----+
enter
选择将包含没有节点的数据。这就是您使用enter时要处理的数据。
假设我们现在更改数据集。我们如何更新DOM节点?
dataset = [ {name: "a",value: 9},value: 3},{name: "d",value: 4} ]
// note how we need to select rect to get the existing data.
// this is the "update" selection
const selection = svg.selectAll("rect")
.data(dataset,d => d.name)
.attr("x",d => d.value)
// the "enter" selection
selection.enter()
.append("rect")
// the "exit" selection
selection.exit().remove()
我们现在有三个选择。如果我们再次绘制图表,现在是这里的数据:
data
data &nodes nodes
+-----+
+--------------------+
| | | |
| d:4 | a:9 | b:2 |
| | | |
| | | |
| | | |
+--------------------+
+-----+
我们进行数据联接时会发生什么?数据已更改。现在svg.selectAll("rect")
进行选择:D3保存在DOM中。 这就是为什么需要将CSS选择器传递给selectAll
的原因。 D3使用该选择器来找到现有选择,并通过每个DOM节点上的.__data__
属性将其保存在DOM中
现在,我们正在观察新数据,并将其与DOM中的数据进行比较:
- a仍然具有数据,并且具有来自先前数据联接的节点。我们知道a仍然存在,但是它的值已经更改,因为我们的数据是带有{name,value}的对象。因此它位于“数据和节点”中。
- b在dom中有一个节点,但在相应的新数据中不存在。在“节点”中。
- d是一个新项目:它是没有节点的数据。因此它包含在“数据”中。
由于c没有更新,所以它不在任何选择范围内。
让我们重命名图中的内容:
enter update exit
+-----+
+--------------------+
| | | |
| d:4 | a:9 | b:2 |
| | | |
| | | |
| | | |
+--------------------+
+-----+
当您直接使用选择(更新选择),致电enter()
或致电exit()
时,您始终在这三个选择中的任何一个上工作。仅在需要时才管理更新,或者不必每次都重新创建节点-仅在需要时销毁它,这样效率更高,尤其对于大数据而言。
即使仅使用enter()
过渡,通过确保仅创建新项目,D3也会更有效。
这个想法是,您可以在render()
之类的函数中放置一个用于管理所有三个状态的代码段,并始终调用它:首次生成图形和更新数据时。 D3为您管理所有数据簿记。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。