如何切换选区中所有元素的类?

时间:2018-05-05 15:50:28

标签: javascript d3.js

我正在尝试编写一个函数,当这些元素还没有该类时,它会为选择中的所有元素添加一个类,反之亦然:

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);
}

3 个答案:

答案 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()给我们!truefalse给我们{{ 1}})并将该否定布尔值传递给!false方法切换选择中的类。

让我们看看它的实际效果:



true

classed