【问题标题】:D3 line chart same tick on hover gives different valuesD3折线图悬停时相同的刻度给出不同的值
【发布时间】:2021-06-14 08:19:27
【问题描述】:

我正在尝试在该确切时间点(x 轴)获取线值,但是相同的刻度给我不同的值取决于我悬停在哪一侧,如果它从左侧表示当前数据index[123]: 10586174,如果我从右侧悬停,它会在 index[124]: 10586174 处显示当前数据。这只是像素差异,因为线条笔划宽度只有 3px,但值不同。这是非常不一致的,一个刻度应该只返回一个与该日期相关的值。

CodeSandbox

//Set up interactions
    d3.selectAll(".xAxis > .tick")
      .style("color", "#65757E")
      .on("mousemove", function (event) {
        event.path[0].style.stroke = "#0D2633";
        d3.select("line").style("z-index", 0);
        const mousePosition = d3.pointer(event, svg.node()); // gets [x,y]
        const currentDate = xScale.invert(mousePosition[0]); // converts x to current date

        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 comparisonDate = xScale2.invert(mousePosition[0]); // converts x to comparison date

        const index_comparisonData = bisect.right(
          comparisonData.values[0].dataset,
          comparisonDate
        );

        if (index_comparisonData < comparisonData.values[0].dataset.length) {
          const tooltipComparisonValue =
            comparisonData.values[0].dataset[index_comparisonData].value;
        }
      })

【问题讨论】:

  • 我建议你稍微重构一下你的代码:你绘制 x 和 y 轴 12 次,每个图有 4 行。重构后,您将更快地解决问题
  • 谢谢你,你能把这个扩展12次吗?还尝试使用两个数据集的最小值和两个数据集的最大值来初始化 xScale,但没有运气。
  • 每次调用 LineChart 都会附加一个 g: with const svg = d3.select(svgRef.current).append("g")

标签: javascript d3.js data-visualization linechart


【解决方案1】:

我可以建议这种方法, 当您创建刻度时,您可以添加带有值的数据属性,例如

    d3.selectAll(".xAxis .tick text")
      .attr("dy", "25px")
      .style("color", "#65757E")
      .style("text-transform", "uppercase")
      // here
      .attr("dataValue", (d) => d);

然后当您处理mousemove时,您将不会采取位置,因为它可能与您的tick值不一致,而是属于目标tick的属性值。

内部事件监听器:

        const currentDate = event.target
          .closest("g")
          .querySelector("text")
          .getAttribute("dataValue");

现在因为你有确切的日期,你可以在你的数据集中找到这个值索引(或只是值),

// find index by comparing the date
const findIndexOfHoveredTick = lineChartData.values[0].dataset.findIndex(
  (d) => new Date(d.date).toString() === currentDate
);

// here you can apply this index to find object inside dataset
lineChartData.values.forEach((value) => {
  console.log(value.dataset[findIndexOfHoveredTick], "Line Value");
});

如果您还需要从comparisonData 获取它,您可以进行相同的操作,或者更好地将它们合并[...lineChartData.values, ...comparisonData.values] 查找同一日期的索引,然后进行计算。

这是有变化的分叉:https://codesandbox.io/s/kind-morning-91fg8?file=/src/LineChart.js:9398-9533

【讨论】:

  • 谢谢。请问您能提供完整的答案吗?我将如何处理 In onmousemove
  • 谢谢,但它不返回该刻度的总值或每行的值?
  • 更新答案,您可以使用我们在悬停时找到的这个日期值,在您的初始数据集中查找任何内容。
猜你喜欢
  • 2015-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
  • 2019-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多