20

在 D3.js 中工作,我想选择与选择器匹配的所有元素,但当前元素除外

原因是我想将鼠标悬停在一个圆圈上,并让具有相同类别的所有其他圆圈变为浅蓝色,但当前圆圈保持相同的阴影。

这是我目前拥有的:

vis.selectAll('circle.prospect')
.on("mouseover", function(d) { 
     console.log(d);
    d3.selectAll('circle.prospect').transition().style('opacity','0.5');
    d3.select(this).attr('opacity','1.0');
  });

在 jQuery 中,我可以使用not. 任何人都知道 D3.js 等价物吗?

4

3 回答 3

27

如果您的元素具有唯一的 CSS 可访问标识符,则可以使用:not()选择器。一些潜在的例子:

d3.selectAll("circle.prospect:not(#" + this.id + ")");
d3.selectAll("circle.prospect:not(." + someUniqueClassFrom(d) + ")");
d3.selectAll("circle.prospect:not([uniqueAttr=" + this.getAttribute('uniqueAttr') + "])");

原因d3.selectAll('circle.prospect:not(this)')不起作用是因为它只是字面上说要过滤掉任何<this></this>元素——这显然不是你的意图,因为它已经只选择了<circle></circle>元素,无论如何都没有效果。

即使您通常不应用一些独特的 DOM 属性,也没有理由不能暂时设置一个:

vis.selectAll('circle.prospect')
.on("mouseover", function(d) {
    this.id = 'temp-' + Math.random();
    d3.selectAll('circle.prospect:not(#' + this.id + ')').transition().style('opacity','0.5');
    d3.select(this).attr('opacity','1.0');
    this.id = '';
  });

但是,如果您的元素尚未分配 ID,我认为 Ian Roberts 的解决方案可能是我会做的,而不是这个临时标识符黑客。

于 2012-09-07T21:45:29.567 回答
18

您可以filter选择:

vis.selectAll('circle.prospect')
.on("mouseover", function(d) { 
     console.log(d);
    var circleUnderMouse = this;
    d3.selectAll('circle.prospect').filter(function(d,i) {
      return (this !== circleUnderMouse);
    }).transition().style('opacity','0.5');
    d3.select(this).attr('opacity','1.0');
  });
于 2012-09-07T15:52:06.530 回答
17

解决这个问题的更简单方法是使用 D3 运算符的强大功能:

vis.selectAll('circle.prospect').on("mouseover", function(d) {
    var circleUnderMouse = this;
    d3.selectAll('circle.prospect').transition().style('opacity',function () {
        return (this === circleUnderMouse) ? 1.0 : 0.5;
    });
});

这里有一个区别,与您的原始代码不同,circleUnderMouse元素的不透明度也将平滑动画。如果它已经完全不透明,那么可能没什么大不了的,否则您可以以类似的方式使用.duration()运算符将 circleUnderMouse 时间加速到 0,其他时间更长。

于 2012-09-07T21:54:31.443 回答