如何在d3中更新单个数据点而不触及其他元素
How to update a single data point in d3 without touching other elements?
我想更新单个数据点并仅修改它绑定的元素,但我不知道如何做到这一点。
这篇文章似乎表明var sel = svg.selectAll(...).data(...)
给出了更新数据的选择,然后sel.enter(...)
代表新数据,然后sel
代表更新+新数据。
在这个jsfiddle示例中,我将新元素着色为绿色,将更新的元素着色为蓝色,但似乎每个现有元素都被着色为蓝色,而不仅仅是自上次更新以来更改的元素。如何更新单个数据?
// ...
function update() {
// clear old classes
svg.selectAll("text").attr("class","");
// join to the new data
var sel = svg.selectAll("text").data(things);
// update -- but this actually affects all elements in the selection?
sel.attr("class","update");
// enter
sel.enter()
.append("text")
.attr("class","enter")
.attr("x", function(d,i) { return 20*i; })
.attr("y", 20);
// update + enter
sel.text(function(d) { return d; });
// exit
sel.exit().remove();
}
正如您所发现的,"update"选项包括所有已存在的元素,准备更新,无论数据是否实际更改。
如果您想测试新数据是否与旧数据相同或不同,您需要一种方法来保存旧数据以与新数据进行比较。然后,您可以使用选择过滤器来丢弃数据相同的元素。
我之前在d3邮件列表中讨论过这个问题。这是我想到的方法:selection = selection.property(" __oldData__", function(d){ return d; } );
//store the old data as a property of the node
.data(newData);
//over-write the default data property with new data
selection.enter() /*etc*/; //handle new elements
selection.filter( function(d) {
//test whether the relevant properties of d match the equivalent in the oldData
//also test whether the old data exists, to catch the entering elements!
return ( (this.__oldData__ ) &&
(d.value != this.__oldData__.value) );
})
.style("fill", "blue");
selection.property("__oldData__", null);
//delete the old data once it's no longer needed
您当然可以为旧的data属性使用任何名称,只是惯例是在它周围添加许多"_"字符,以避免混淆浏览器的任何本机DOM属性。你不需要在之后删除oldData(它将在下次更新时被覆盖),但是如果你不经常更新,它可以节省内存来显式释放它。
注意selection.filter()
不保留索引值。如果您需要跟踪i
,您可以添加一个额外的步骤来保存索引,然后将其作为一个单独的属性(元素或数据对象的属性)进行过滤,或者您可以跳过过滤器,直接在style/attr调用中的函数中进行测试。
编辑:我已经改变了过滤器功能,相对于链接的讨论,所以它只有包含更新的元素,而不是新的或更新的元素。无论哪种方式,过滤器都会选择过滤器函数返回true的元素。
在您的情况下,弄清楚这一点相对容易。您将元素的文本设置为数据,因此在确定数据是否已更新时,只需比较它们:
sel.classed("update", function(d) { return d != d3.select(this).text(); });
完整演示在这里。关于一般解决方案,请参见amelabr的答案。
- 从异步调用返回数组,然后为数组的每个元素返回其他异步调用
- 如何使用可调整大小的元素重叠其他元素
- 如何选择仅包含链接的块级元素及其父元素
- jQuery don'当元素被其他元素检索时,它不能正常工作
- 从页面中删除除数组中包含的元素及其父元素/子元素之外的所有元素
- 如果 e.keyCode 是“输入”按钮,并且元素包含其他文本,则验证条件
- jQuery UI 可拖动元素位于其他可拖动元素下
- 在单击时对元素进行动画处理,并在该元素和其他元素上单击鼠标输入/鼠标离开
- Matrix3d 属性值及其他
- 如何仅触发表单元素与其他代码的部分更改
- 是否可以使用 Javascript 库测试 SVG 元素?任何其他选项
- 将元素放在其他元素的内部HTML中
- 元素及其父元素指定了 ng-单击,两者都被调用
- 如何将不同的事件处理程序分配给元素及其父级
- 当调用jQuery's.trigger()函数到绑定到该元素的其他处理程序的传播停止
- jQueryUI-拖放问题-拖动的元素位于其他DOM元素之后
- 为什么一个内联块元素比其他元素略高
- 不能移动DOM元素到其他位置
- 使用jQuery或JavaScript访问表单中的元素(或其他包含元素)
- 通过点击原始元素或其他元素来切换可见性