d3 повышение () не работает на конкретном выборе - PullRequest
0 голосов
/ 25 декабря 2018

У меня есть линейная диаграмма, созданная с d3, но из-за формы данных линии и точки (я использую точки над линиями для каждой конкретной точки данных) обычно оказываются друг над другом.

Чтобы противостоять этой проблеме, я прекратил придавать непрозрачность 0.4 линиям и точкам, а когда вы наводите курсор мыши на линию, всплывают линии и точки этой конкретной строки данных и задается ее непрозрачность.на 1.

Моя проблема в том, что я использую функцию .raise(), чтобы заставить их всплывать и стоять над остальными линиями и точками, функция работает только с моим выбором линий ине с моим выбором точек, и я не знаю почему.

Мой код:

// draw the data lines
    const lines = svg.selectAll('.line')
      .data(this.data)
      .enter()
      .append('path')
      .attr('class', 'data.line')
      .attr("fill", "none")
      .attr("stroke", d => colors(d.key))
      .attr("stroke-linejoin", "round")
      .attr("stroke-linecap", "round")
      .attr("stroke-width", 2.5)
      .attr('stroke-opacity', 0.4)
      .attr('d', d => line(d.values))
      .on('mouseenter', d => {
        // Highlight them
        let myCircles = circles.selectAll('.circle');
        lines.attr('stroke-opacity', b => {
          return b.key === d.key ? 1 : 0.4;
        });
        myCircles.attr('fill-opacity', b => {
          return b[this.typeIdentifier] === d.key ? 1 : 0.4;
        });
        // Bring them to the front
        myCircles = circles.selectAll('.circle')
          .filter(b => b[this.typeIdentifier] === d.key);
        const myLines = lines.filter(b => b.key === d.key);
        myLines.raise();
        myCircles.raise();
      });

// draw the circles
    const circles = svg.selectAll('.circle')
      .data(this.data)
      .enter()
      .append('g');

    circles.selectAll('.circle')
      .data(d => d.values)
      .enter()
      .append('circle')
      .attr('class', 'circle')
      .attr('stroke', 'white')
      .attr('stroke-width', 1)
      .attr('r', 6)
      .attr('fill', d => colors(d[this.typeIdentifier]))
      .attr('fill-opacity', 0.4)
      .attr('cx', d => x(d[this.xAxisValue]) + x.bandwidth() / 2)
      .attr('cy', d => y(d[this.yAxisValue]))
      .on('mouseenter', (d, b, j) => {
        tooltip.raise();
        tooltip.style("display", null);
        tooltip.select("#text1").text(d[this.typeIdentifier])
          .attr('fill', colors(d[this.typeIdentifier]));
        tooltip.select('#text4').text(d[this.yAxisValue]);
        tooltip.select('#text5').text(d[this.xAxisValue]);
        const tWidth = tooltip.select('#text1').node().getComputedTextLength() > 60 ? tooltip.select('#text1').node().getComputedTextLength() + 20 : 80;
        tooltipRect.attr('width', tWidth);
        const xPosition = d3.mouse(j[b])[0];
        const yPosition = d3.mouse(j[b])[1];
        if (xPosition + tWidth + 35 < this.xWIDTH) {  // display on the right
          tooltip.attr("transform", `translate(${xPosition + 15}, ${yPosition - 25})`);
        } else {  // display on the left
          tooltip.attr("transform", `translate(${xPosition - tWidth - 15}, ${yPosition - 25})`);
        }
      })
      .on('mouseleave', d => {
        tooltip.style("display", "none");
      })

Итак, когда вы наводите курсор мыши на линию, это должно привести к линии и точкамсвязанный с ним спереди, с непрозрачностью 1, но по какой-то причине он работает только с выбором lines, а не с выбором myCircles.Выбор не пустой, и я печатаю их все время, чтобы проверить это.Кроме того, я попытался вывести круги один за другим (с единичными выделениями и необработанными элементами) на фронт, используя метод .raise(), и он не работает eiter.

Почему он не работает?Может ли это иметь отношение к всплывающей подсказке при наведении на круги?Я что-то делаю не так и не вижу?

1 Ответ

0 голосов
/ 30 декабря 2018

На самом деле, selection.raise() работает.Проблема здесь только в древовидной структуре вашего SVG: все круги для данной линии принадлежат элементу <g>.

Если вы посмотрите на документы , вы увидитечто selection.raise():

Повторно вставляет каждый выбранный элемент по порядку как последний дочерний элемент его parent .

Выделение вышеЭто мое: ключевая работа здесь - родитель .Итак, вам нужно поднять элемент <g>, содержащий выделенные круги, над другими элементами <g> для других кругов, а не кругов внутри их <g> родительского элемента.

В вашем случае,это так же просто, как изменить ...

myCircles = circles.selectAll('.circle').filter(etc...)

... на:

myCircles = circles.filter(etc...)

Теперь myCircles - это выделение с элементом <g>, которое вы можете поднять,Обратите внимание на функцию filter: поскольку вы не предоставили доступ к своей структуре данных, я не знаю, содержит ли массив данных для элементов <g> (то есть this.data) свойство key.Измените его соответствующим образом.

Вот демонстрационная версия:

У нас есть набор окружностей для каждой строки, каждый из которых находится внутри собственного <g> родителя.Разделяются только левые круги, все остальные круги специально нарисованы один над другим.Когда вы наводите курсор на круг (используйте те, что слева), его контейнер <g> поднимается, в этом случае, используя ...

d3.select(this.parentNode).raise()

..., так что все круги видны:

const svg = d3.select("svg");
const scale = d3.scaleOrdinal(d3.schemeSet1);
const lineGenerator = d3.line()
  .x(function(d) {
    return d.x
  })
  .y(function(d) {
    return d.y
  })
const data = d3.range(5).map(function(d) {
  return {
    key: d,
    values: d3.range(5).map(function(e) {
      return {
        x: 50 + 100 * e,
        y: e ? 150 : 50 + 50 * d
      }
    })
  }
});
const lines = svg.selectAll(null)
  .data(data)
  .enter()
  .append("path")
  .attr("d", function(d) {
    return lineGenerator(d.values);
  })
  .style("fill", "none")
  .style("stroke-width", "3px")
  .style("stroke", function(d) {
    return scale(d.key)
  });
const circleGroups = svg.selectAll(null)
  .data(data)
  .enter()
  .append("g");
const circles = circleGroups.selectAll(null)
  .data(function(d) {
    return d.values
  })
  .enter()
  .append("circle")
  .attr("r", 20)
  .attr("cx", function(d) {
    return d.x
  })
  .attr("cy", function(d) {
    return d.y
  })
  .style("fill", function(d) {
    return scale(d3.select(this.parentNode).datum().key)
  });
circles.on("mouseover", function(d) {
  const thisKey = d3.select(this.parentNode).datum().key;
  lines.filter(function(e) {
    return e.key === thisKey;
  }).raise();
  d3.select(this.parentNode).raise();
})
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg width="500" height="300"></svg>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...