我正在尝试编写一个函数,当这些元素还没有该类时,它会为选择中的所有元素添加一个类,反之亦然:
function toggleLinksActivity(d) {
d3.selectAll(".link")
.filter(l => l.target == d)
.classed("non-active", l => !l.classed("non-active"));
}
这给出了.classed
不是函数的错误。 documentation表示应该在选择中调用.classed
,因此我尝试将最后一行更改为!d3.select(l).classed("non-active")
,但这也不起作用(" t.getAttribute不是功能")。出了什么问题,正确的方法是什么?
注意:我已经用下面的2个单独的函数解决了我的问题,但是我发现将切换分成2部分很难看。
function activateLinks(d) {
d3.selectAll(".link")
.filter(l => l.target == d)
.classed("non-active", false);
}
function deactivateLinks(d) {
d3.selectAll(".link")
.filter(l => l.target == d)
.classed("non-active", true);
}
答案 0 :(得分:4)
Gerardo的answer使用Element.classList
指向正确的方向,但建议的解决方案仍然可以简化。事实证明,classList
属性已经采用.toggle()
方法,其工作方式如下:
toggle(String [,force])
当只有一个参数时:切换类值;即,如果类存在则删除它并返回false,否则返回false,然后添加它并返回true。 当存在第二个参数时:如果第二个参数的计算结果为true,则添加指定的类值,如果计算结果为false,则将其删除。
您的功能可以写成:
function toggleLinksActivity(d) {
d3.selectAll(".link")
.each(function(l) {
if (l.target == d) {
this.classList.toggle("non-active");
}
});
}
答案 1 :(得分:2)
您需要重新选择第i个元素并使用其classed
属性:
function toggleLinkActive() {
d3.selectAll(".link")
.classed("non-active", (d,i,nodes) => !d3.select(nodes[i]).classed("non-active"));
}
如果您使用的是非箭头功能,也可以选择this
:
function toggleLinkActive() {
d3.selectAll(".link")
.classed("non-active", function() { return !d3.select(this).classed("non-active"); });
}
如果您想避免重新选择该项目,可以使用each
并将选择内容存储在变量中:
function toggleLinkActive() {
d3.selectAll(".link")
.each(function() {
const item = d3.select(this);
item.classed("non-active", !item.classed("non-active"));
});
或者您可以使用@altocumulus的答案中的原生this.classList.toggle("non-active")
。
答案 2 :(得分:2)
我们可以使用classList而不是再使用D3 classed
方法 ,而是使用一个更短且更优雅的函数来切换类,该函数使用一元否定和{ {1}}检查选择是否具有给定的类。
在我提议的函数中,您必须传递选择和类的名称。它只是这个:
contains
这个函数背后的逻辑很简单:function toggleClass(selection, className) {
selection.classed(className, !selection.node().classList.contains(className))
}
返回一个布尔值...所以,否定它(contains()
给我们!true
和false
给我们{{ 1}})并将该否定布尔值传递给!false
方法切换选择中的类。
让我们看看它的实际效果:
true

classed