Подсказка не отображается в добавленном 'прямоугольнике' в верхней части точки / окружности на графике d3 - PullRequest
0 голосов
/ 24 февраля 2020

У меня есть линейная диаграмма d3 с всплывающей подсказкой, у меня возникла проблема с всплывающей подсказкой.

У меня есть функциональность, при нажатии точек / окружности я добавляю rect к g, что добавляет поверх существующего rect, который имеет функцию всплывающей подсказки.

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

g.append("rect")
      .attr("class", "overlay")
      .attr("id", "firstLayer")
      .attr("width", width)
      .attr("height", height)

      .on("mouseover", function(d) {
        focus.style("display", null);
        div
          .transition()
          .duration(200)
          .style("opacity", 0.9);
      })

      .on("click", function(d, index) {
        let newXScale = newX ? newX : xScale;
        if (rect) rect.remove();
        rect = g
          .append("rect")
          .attr("x", newXScale(d.startTime) - 12.5)
          .attr("y", 0)
          .attr("width", 24)
          .attr("height", height + 5)
          .attr("data", d.startTime)
          .style("fill", "steelblue")
          .style("opacity", 0.5);

        if (clickLine) clickLine.remove();
        clickLine = g
          .append("line")
          .attr("x1", newXScale(d.startTime))
          .attr("y1", yScale(yDomain[0]))
          .attr("x2", newXScale(d.startTime))
          .attr("y2", yScale(yDomain[1]))
          .attr("class", "focusLine")
          .style("opacity", 0.5);
      })

rect элемент появляется в верхней части панели при наведении этой подсказки не приходит, никаких предложений как это исправить?

При наведении мыши - enter image description here

В выбранной точке графика -

enter image description here

Ссылка CodeSandbox ниже - https://codesandbox.io/s/damp-dawn-82hxc

Пожалуйста, подскажите, что можно изменить.

1 Ответ

3 голосов
/ 25 февраля 2020

при нажатии circle вы добавляете еще один прямоугольник к g, который добавляет поверх существующего rect, который имеет функциональность tool tip

Примечание: d3 js добавляет слой / форму поверх другого, который в основном переопределяет существующую функциональность слоя / формы с новым слоем / формой, если они находятся в том же position

Чтобы избежать этого, мы должны рисовать слои в зависимости от их предназначения и положения.

Решение вышеуказанной проблемы

добавить фон rects для circle, который вы хотите создать с помощью opacity: 0

g.selectAll(".faaa")
  .data(data)
  .enter()
  .append("rect")
  .attr("class", "faaa")
  .attr("id", d => "rect_" + d.id)
  .attr("x", d => xScale(d.startTime) - 12.5)
  .attr("y", 0)
  .attr("width", 24)
  .attr("height", height + 5)
  .attr("data", d => d)
  .style("fill", "steelblue")
  .style("opacity", 0);

append firstLayer rect, который имеет функцию всплывающей подсказки, поэтому фон rect не нарушит tooltip функциональность

g.append("rect")
  .attr("class", "overlay")
  .attr("id", "firstLayer")
  .attr("width", width)
  .attr("height", height)

  .on("mouseover", function(d) {
    focus.style("display", null);
    div
      .transition()
      .duration(200)
      .style("opacity", 0.9);
  })
  .on("mouseout", function() {
    focus.style("display", "none");
    div
      .transition()
      .duration(300)
      .style("opacity", 0);
  })

  .on("mousemove", function() {
    var mouse = d3.mouse(this);
    var mouseDate = xScale.invert(mouse[0]);
    var i = bisectDate(data, mouseDate); // returns the index to the current data item

    var d0 = data[i - 1];
    var d1 = data[i];
    let d;
    // work out which date value is closest to the mouse
    if (typeof d1 !== "undefined") {
      d = mouseDate - d0.startTime > d1.startTime - mouseDate ? d1 : d0;
    } else {
      d = d0;
    }

    div
      .html(
        `<span>${parseDate(d.startTime)}</span>
        <span> Changes : ${d.magnitude} % </span>`
      )
      .style("left", d3.event.pageX + "px")
      .style("top", d3.event.pageY - 28 + "px");
    var x = xScale(d.startTime);
    var y = yScale(d.magnitude);

    focus
      .select("#focusCircle")
      .attr("cx", x)
      .attr("cy", y);
    focus
      .select("#focusLineX")
      .attr("x1", x)
      .attr("y1", yScale(yDomain[0]))
      .attr("x2", x)
      .attr("y2", yScale(yDomain[1]));
    focus
      .select("#focusLineY")
      .attr("x1", xScale(xDomain[0]))
      .attr("y1", y)
      .attr("x2", xScale(xDomain[1]))
      .attr("y2", y);
  });

добавьте circle и добавьте click функциональность, затем измените opacity, чтобы выделить фон rect

  g.selectAll(".foo")
    .data(data)
    .enter()
    .append("circle")
    .attr("id", d => d.id)
    .attr("class", "foo")
    .attr("data", d => d)
    .attr("cx", function(d) {
      return xScale(d.startTime);
    })
    .attr("cy", function(d) {
      return yScale(d.magnitude);
    })
    .attr("r", function(d) {
      return 6;
    })
    .on("click", function(d) {
      // change the opacity here
      d3.select("#rect_" + d.id).style("opacity", 0.5);
    })
    .attr("class", "circle");

Надеюсь, что это решит вышеуказанную проблему ...

...