Working in D3.js, I'd like to select all the elements that match a selector except for the current element.
在D3.js中工作,我想选择除当前元素之外的所有与选择器匹配的元素。
The reason is that I'd like to mouseover a circle, and have all the other circles with the same class turn light blue, but the current circle to stay the same shade.
原因是我想鼠标移动一个圆圈,并让所有其他同一类的圆圈变为浅蓝色,但当前圆圈保持相同的阴影。
This is what I have currently:
这就是我目前所拥有的:
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');
});
In jQuery, I could do this using not
. Anyone know the D3.js equivalent?
在jQuery中,我可以使用not来做到这一点。有人知道D3.js相当吗?
3 个解决方案
#1
14
An even simpler way to approach this would be using the power of D3's operators:
更简单的方法是使用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;
});
});
There's one difference here in that, unlike your original code, the circleUnderMouse
element's opacity will be smoothly animated as well. If it's already fully opaque then probably not a big deal, otherwise you could use the .duration() operator in a similar fashion to speed the circleUnderMouse time to 0 and the others longer.
这里有一个区别,与原始代码不同,circleUnderMouse元素的不透明度也将平滑地动画。如果它已经完全不透明,那么可能没什么大不了的,否则你可以以类似的方式使用.duration()运算符来将circleUnderMouse时间加速到0而其他时间更长。
#2
22
If your elements have an unique CSS-accessible identifiers, you can use the :not()
selector. Some potential examples:
如果您的元素具有唯一的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') + "])");
The reason d3.selectAll('circle.prospect:not(this)')
doesn't work is because it's just literally saying to filter out any <this></this>
elements — which is obviously not your intent, and since it's already selecting only <circle></circle>
elements would have no effect regardless.
d3.selectAll('circle.prospect:not(this)')不起作用的原因是因为它只是字面意思来过滤掉任何
Even if you don't generally apply some unique DOM attribute, there's no reason you couldn't set one temporarily:
即使您通常不应用某些唯一的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 = '';
});
That said, however, if your elements don't already have an ID assigned already, I think Ian Roberts' solution is probably what I would do instead of this temporary identifier hack.
但是,如果您的元素尚未分配ID,我认为Ian Roberts的解决方案可能就是我要做的,而不是这个临时标识符黑客攻击。
#3
18
You can filter
a selection:
您可以过滤选择:
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');
});
#1
14
An even simpler way to approach this would be using the power of D3's operators:
更简单的方法是使用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;
});
});
There's one difference here in that, unlike your original code, the circleUnderMouse
element's opacity will be smoothly animated as well. If it's already fully opaque then probably not a big deal, otherwise you could use the .duration() operator in a similar fashion to speed the circleUnderMouse time to 0 and the others longer.
这里有一个区别,与原始代码不同,circleUnderMouse元素的不透明度也将平滑地动画。如果它已经完全不透明,那么可能没什么大不了的,否则你可以以类似的方式使用.duration()运算符来将circleUnderMouse时间加速到0而其他时间更长。
#2
22
If your elements have an unique CSS-accessible identifiers, you can use the :not()
selector. Some potential examples:
如果您的元素具有唯一的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') + "])");
The reason d3.selectAll('circle.prospect:not(this)')
doesn't work is because it's just literally saying to filter out any <this></this>
elements — which is obviously not your intent, and since it's already selecting only <circle></circle>
elements would have no effect regardless.
d3.selectAll('circle.prospect:not(this)')不起作用的原因是因为它只是字面意思来过滤掉任何
Even if you don't generally apply some unique DOM attribute, there's no reason you couldn't set one temporarily:
即使您通常不应用某些唯一的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 = '';
});
That said, however, if your elements don't already have an ID assigned already, I think Ian Roberts' solution is probably what I would do instead of this temporary identifier hack.
但是,如果您的元素尚未分配ID,我认为Ian Roberts的解决方案可能就是我要做的,而不是这个临时标识符黑客攻击。
#3
18
You can filter
a selection:
您可以过滤选择:
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');
});