D3 折线图 return 鼠标悬停时的值不正确

D3 Line chart doesn't return correct value on ticks mouse over

我有一张折线图,包含当年和比较年/上一时期。我想在悬停时显示工具提示,因此它将显示当前年份和比较年份的当前刻度值。但是,我注意到返回的总价值与 y 轴上的金额不匹配(请参见下面的屏幕截图)。

根据上图,该值应在 30M - 40M 之间,但显示为 56150248.2。

CodeSandbox

// tooltip on x axis
    d3.selectAll(".xAxis > .tick")
      .style("color", "#65757E")
      .on("mouseover", function (d) {
        console.log("data");
        const mousePosition = d3.pointer(d);
        const data = yScale.invert(mousePosition[0]);
        console.log("pos", mousePosition);
        console.log("data", data);
      })
      .on("mouseout", (d) => {
        console.log("test");
      });

发生以下情况:

  • 您选择的鼠标悬停是 d3.selectAll(".xAxis > .tick")
  • 在线:.on("mouseover", function (d) { 参数 d 指的是正在传递的事件。我建议 称它为 event 而不是 d 否则它会混淆
  • mousePosition 由一个具有奇怪坐标的数组初始化,即相对于选择(即刻度)的坐标

参见:d3.pointer(event[, target])

Returns a two-element array of numbers [x, y] representing the coordinates of the specified event relative to the specified target. event can be a MouseEvent, a PointerEvent, a Touch, or a custom event holding a UIEvent as event.sourceEvent.

If target is not specified, it defaults to the source event’s currentTarget property, if available. If the target is an SVG element, the event’s coordinates are transformed using the inverse of the screen coordinate transformation matrix. If the target is an HTML element, the event’s coordinates are translated relative to the top-left corner of the target’s bounding client rectangle. (As such, the coordinate system can only be translated relative to the client coordinates. See also GeometryUtils.) Otherwise, [event.pageX, event.pageY] is returned.

  • const data = yScale.invert(mousePosition[0]); 你指的是用 mousePosition[0] 的 x 位置,你可能是指 mousePosition[1]

要使用通过 yscale 反转的坐标,您希望坐标相对于直接位于 svg 下的翻译 g。您已经选择了变量 svg 引用的那个元素。

// tooltip on the g child of the svg
    svg  
      .style("color", "#65757E")
      .on("mouseover", function (event) {
        console.log("data");
        const mousePosition = d3.pointer(event);
        const data = yScale.invert(mousePosition[1]);
        console.log("pos", mousePosition);
        console.log("data", data);
      })
      .on("mouseout", (event) => {
        console.log("test");
      });

更新 06/13/2021 基于以下评论: 你可能想做这样的事情(不确定我是否引用了正确的数据,但你可以这样做:

d3.selectAll(".xAxis > .tick")  
      .style("color", "#65757E")
      .on("mousemove", function (event) {
        const mousePosition = d3.pointer(event, svg.node()); // gets [x,y]
        console.log("mouse position:", mousePosition);
        const currentDate = xScale.invert(mousePosition[0]); // converts x to date
        console.log("date at position:", currentDate);
        const bisect = d3.bisector(d => new Date(d.date)) // create a bisector

        const index_currentData = bisect.right(lineChartData.values[0].dataset, currentDate);     
        if (index_currentData < lineChartData.values[0].dataset.length) {
          console.log(`Current data at index[${index_currentData}]: ${lineChartData.values[0].dataset[index_currentData].value}`);
        }

        const index_comparisonData = bisect.right(comparisonData.values[0].dataset, currentDate);     
        if (index_comparisonData < comparisonData.values[0].dataset.length) {
          console.log(`Comparison data at index[${index_comparisonData}]: ${comparisonData.values[0].dataset[index_comparisonData].value}`);
        }
      })