Является ли querySelectorAll хорошим способом выбора элементов в нескольких графиках?

1

Я хотел бы выделить элементы из одного измерения (страны в этом примере) на нескольких графиках. Назначение класса каждой стране в точке генерации 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');}
    })
  • 0
    Обмен стеками обзора кода - лучшее место, чтобы спросить это. Так как ваш код хотя бы работает. codereview.stackexchange.com
  • 0
    Я также рекомендовал CodeReview для подобных вопросов, но я получил много жалоб от пользователей CR, которые препятствуют такой миграции. Итак, сегодня я рекомендую CodeReview только по очень конкретным вопросам.
Показать ещё 2 комментария
Теги:
d3.js

1 ответ

2
Лучший ответ

Как вы можете видеть из исходного кода, 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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню