Эквивалент селектора jQuery 'not' в D3.js?
Работая в 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?
Ответы
Ответ 1
Еще более простой способ приблизиться к этому - использовать мощность 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, а остальные больше.
Ответ 2
Если ваши элементы имеют уникальные идентификаторы, доступные для 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 = '';
});
Однако, если у ваших элементов уже нет идентификатора, который уже назначен, я думаю, что решение Яна Робертса, вероятно, будет тем, что я сделал бы вместо этого временного хакера.
Ответ 3
Вы можете 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');
});