d3.js D3折线图未在鼠标悬停的分笔成交点上返回正确值

iezvtpos  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(131)

我有一个包含当前年份和比较年份/上一期间的折线图。我希望在悬停时显示工具提示,这样它将同时显示当前年份和比较年份的当前分笔成交点值。但是,我注意到返回的总值与y轴上的金额不匹配(请参见下面的屏幕截图)。

根据上图,该值应在30 M-40 M之间,但显示为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");
      });
66bbxpm5

66bbxpm51#

发生的情况如下:

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

请参阅:d3.pointer(事件[,目标])
返回数字[x,y]的双元素数组,表示指定事件相对于指定目标的坐标。事件可以是MouseEvent、PointerEvent、Touch或将UIEvent保存为event.sourceEvent的自定义事件。
如果未指定target,它会预设为来源事件的currentTarget属性(如果有的话)。如果目的是SVG元素,则会使用屏幕坐标转换矩阵的逆矩阵来转换事件的坐标。如果目的是HTML元素,则会相对于目的的周框客户端矩形的左上角来转换事件的坐标。(因此,坐标系只能相对于客户端坐标进行转换。另请参阅GeometryUtils。)否则,将返回[event.pageX,event.pageY]。

  • 对于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");
      });

根据以下评论于2021年6月13日更新:您可能需要执行类似以下的操作(不确定是否引用了正确的数据,但您可以从以下内容开始工作:

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}`);
        }
      })

相关问题