Recharts:如何才能在工具提示中仅显示一个数据点的值?

Mar*_*lli 7 tooltip reactjs recharts

我试图在 Recharts LineChart 中实现以下示例:工具提示值相对于蓝点,因为我的鼠标恰好靠近它,并且距离具有相同 x 值的灰点更远。如果我将鼠标移近灰点,工具提示内容会发生变化。

工具提示仅显示有关一个数据系列的数据

然而,所有可用的示例都表明,图表工具提示接收有关正在绘制的所有数据系列的数据,并且似乎无法区分最接近鼠标的点,因此工具提示可能仅提供其值。

有没有办法指定我想要将数据发送到工具提示的点?

Mar*_*lli 7

在经过长时间的无果搜索后,我决定自己解决这个问题。最少的代码发布在这个 Github gist中。

要解决的基本问题是任何标准 Recharts 工具提示都会接收以下信息:

  • 鼠标指针当前所在的 x 值,以图表画布上的像素表示
  • 与鼠标 x 值最接近位置的所有数据系列的 y 值,以 y 轴实际单位(欧元、千克等)表示

因此,还需要向自定义工具提示提供以图表画布上的像素表示的 y 轴鼠标位置信息。然后,工具提示可以计算哪个数据系列最接近垂直鼠标位置,并仅显示属于该数据系列的值。

提取以像素为单位的 y 位置很棘手,因为 Recharts 每次重新绘制图表时都会更改像素和纵坐标值之间的映射。但是有一个图表组件必须非常了解这种映射,以便将自己放置在正确的垂直位置并显示相应的现实世界坐标值:即 y 轴上的每个刻度

问题是:我们如何插入 Recharts 绘图工作流程以了解映射?

方法如下:Recharts 组件的tickYAxis属性允许提供自定义 React 组件,尽管没有示例记录。对于 Recharts 决定放置在 y 轴上的每个刻度,此自定义组件都会实例化一次。通过反复试验,我发现我的自定义 Tick 组件具有以下属性:

{ x, y, payload, ...anyCustomPropertyAddedByMe }
Run Code Online (Sandbox Code Playgroud)

其中xy是刻度线(画布像素)的笛卡尔坐标,并且payload是这样一个对象:

{ coordinates, isShow, offset, tickCoord, value }
Run Code Online (Sandbox Code Playgroud)

其中value以现实世界的 y 轴单位表示。

这个想法是找出(y, value)每张图中最低和最高刻度的对,并计算像素和实际值之间的转换因子。 这将允许自定义工具提示执行上述计算。(严格来说,从每个图表重绘时实例化的前两个刻度中收集两对就足够了,但选择相距最远的两个可以提供更高的精度)

整个算法分为三个部分:

  • tooltipCollector :这是一个 JavaScript模块,提供两种方法

    1. collect(value, y),由自定义刻度调用,将所有对存储(y, value)在私有数组中_collection
    2. maxAndMin(),由自定义工具提示调用,它读取数组_collection并返回集合中代表最低和最高刻度的几个项目(请注意画布中的垂直像素值是颠倒测量的!)
  • 一个定制的 Tick React 组件:

    1. 在其自定义属性中接收工具提示收集器
    2. 通过调用其方法将其y和发送payload.value到收集器collect(y, value)
    3. 返回一个非常简单的 JSX 刻度标记,该标记使用y(将其自身放置在正确的垂直位置)和payload.value(向用户显示刻度指示的实际值)
  • CustomTooltip React组件:

    1. 在其自定义属性中接收工具提示收集器并调用其maxAndMin()方法
    2. 使用阈值验证(通过考虑其 prop coordinate.y)它是否足够接近图表数据系列之一;这确保仅当鼠标光标非常接近图表上的点时才绘制工具提示
    3. 修改其返回的 JSX 标记以仅包含与鼠标最接近的数据系列相关的值;如果图表中的更多点比阈值更接近,工具提示将显示多个值

我的要点中的代码已被简化,以删除所有不必要的 JSX 标记。它提供了一个图表组件,可以使上述所有组件发挥作用。

单值 CustomTooltip 的实际应用

请注意,突出显示工具提示横坐标指向的所有数据系列点的标准 Recharts 行为尚未更改。因此,最好在工具提示内容中放置颜色代码,以清楚地说明显示的值属于哪个数据系列。