Я хотел бы выделить элементы из одного измерения (страны в этом примере) на нескольких графиках. Назначение класса каждой стране в точке генерации rect
или circle
а затем использование querySeletorAll
для поиска всех соответствующих элементов, похоже, работает, но мне интересно, есть ли лучший способ. Это немного хакерски.
Пожалуйста, посмотрите этот блок для рабочего демо.
И гистограмма, и разброс имеют классы, назначенные их элементам (rect
и circle
) одинаково:
var enter = svgContainer.selectAll('rect')
.data(data)
.enter().append('rect')
.attr('class', function(d) { return "mycharts_bars_" + d.Country; })
И тогда выделение при наведении делает это:
.on("mouseover", function(d) {
var hover_value = this.__data__.Country;
var hover_elems = document.querySelectorAll('[class*="${hover_value}"]');
for (let item of hover_elems) {
item.setAttribute('fill', 'hotpink');}
})
Как вы можете видеть из исходного кода, d3.selectAll
уже использует document.querySelectorAll
внутреннего использования:
export default function(selector) {
return typeof selector === "string"
? new Selection([document.querySelectorAll(selector)], [document.documentElement])
: new Selection([selector == null ? [] : selector], root);
}
Таким образом, вы можете безопасно использовать selectAll
, что делает ваш код более понятным для программистов D3.
Однако в вашем коде есть некоторые проблемы:
Во-первых, вам не нужно это var hover_value = this.__data__.Country;
, У вас уже есть данные в качестве первого аргумента! Поэтому это может быть просто d.Country
.
Во-вторых, вам не нужно иметь дело с классами, если вы не хотите, просто выберите элемент. Вы можете использовать классы, если хотите, это не большая проблема, но вам определенно не нужно это for...of
цикла. Как правило, не используйте циклы в коде D3 (есть определенные ситуации, когда они необходимы, но не в этом).
Все это, как говорится, функция может быть просто так:
d3.selectAll("circle, rect").attr("fill", function(e) {
return e.Country === d.Country ? "pink" : "grey"
});
Или, поскольку только прямоугольник завис над ним изменит цвет:
d3.select(this).attr("fill", "pink");
d3.selectAll("circle").attr("fill", function(e) {
return e.Country === d.Country ? "pink" : "grey"
});
Как примечание стороны, это изменит все выбранные элементы на странице. Я делаю это только потому, что в вашем примере у вас очень мало элементов. Если в вашей реальной диаграмме у вас есть сотни элементов, лучшим решением будет сначала отфильтровать их, а затем применить изменения (как при mouseover
и при mouseout
), что даст вам лучшую производительность.
Вот ваш код с этим изменением: https://blockbuilder.org/GerardoFurtado/e54f2f0cc711b51be4b400627cac6f51