关于 React 如何自定义配置 HighCharts tooltip

前言

当我们结合 React 使用 highCharts 库时,存在一些特殊自定义的情况,比如针对 Tooltip 定制化样式。当然 highCharts 也提供了配置自定义 tooltip 的 formatter 方法,可以支持 html 元素。但是并不够灵活,对于配置复杂样式或组件复用情况下,并不友好。因此寻求新的思路,以下便是社区常用的一个方法,在此记录。

实现

Tooltip 组件封装

import {
   
  Chart,
  TooltipFormatterCallbackFunction,
  TooltipFormatterContextObject,
} from 'highcharts';
import {
    useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom';

const generateTooltipId = (chartId: number) =>
  `highcharts-custom-tooltip-${
     chartId}`;

interface Props {
   
  chart: Chart | null;
  children(formatterContext: TooltipFormatterContextObject): JSX.Element;
}

export const Tooltip = ({
     chart, children }: Props) => {
   
  const isInit = useRef(false);
  const [context, setContext] = useState<TooltipFormatterContextObject | null>(
    null
  );

  useEffect(() => {
   
    if (chart) {
   
      const formatter: TooltipFormatterCallbackFunction = function () {
   
        // Ensures that tooltip DOM container is rendered before React portal is created.
        if (!isInit.current) {
   
          isInit.current = true;

          setTimeout(() => {
   
            chart.tooltip.refresh.apply(chart.tooltip, [
              this.points ? this.points.map(({
     point }) => point) : this.point,
            ]);
            chart.tooltip.hide(0);
          });
        }

        setContext(this);

        return `<div id="${
     generateTooltipId(chart.index)}"></div>`;
      };

      chart.update({
   
        tooltip: {
   
          formatter,
          useHTML: true,
        },
      });
    }
  }, [chart]);

  const node = chart && document.getElementById(generateTooltipId(chart.index));

  return node && context
    ? ReactDOM.createPortal(children(context), node)
    : null;
};

调用方式

import React, {
    useState, useCallback } from "react";
import Highcharts, {
    Chart as HighchartsChart } from "highcharts";
import HighchartsReact from "highcharts-react-official";
import {
    Tooltip } from "./Tooltip";

const options = {
   
  title: {
   
    text: "Custom tooltip as React component"
  },
  series: [
    {
   
      type: "line",
      data: [1, 22424242424, 3, 4, 5, 123123132]
    }
  ],
  tooltip: {
   
    useHTML: true
  }
};

export const Chart = () => {
   
  const [chart, setChart] = useState<HighchartsChart | null>(null);
  const callback = useCallback((chart: HighchartsChart) => {
   
    setChart(chart);
  }, []);

  return (
    <>
      <HighchartsReact
        highcharts={
   Highcharts}
        options={
   options}
        callback={
   callback}
      />

      <Tooltip chart={
   chart}>
        {
   (formatterContext) => {
   
          const {
    x, y } = formatterContext;
          return (
            <>
              <div>x: {
   x}</div>
              <div>y: {
   y}</div>
              <br />
              <button onClick={
   () => alert(`x: ${
     x}, y: ${
     y}`)}>Action</button>
            </>
          );
        }}
      </Tooltip>
    </>
  );
};

formatterContext 里包含以下常用的字段:

{
   
	points
	point
	series
	x
	y
}

这些字段在自定义 tooltip 组件时可以传参到组件中获取每个 point 的值。
除了 x,y 值外,可以自定义字段,在 series.keys 配置项中,配置如下:

keys: [
  'x',
  'y',
  'custom.A',
  'custom.B',
  'custom.C',
],
data:[[1, 2, 'A1', 'B1', 'C1'], [1, 2, 'A2', 'B2', 'C2']]

其值便可以在 formatterContext.point.options.custom.AformatterContext.point.options.custom.B 等方式获取。

总结

该实现方式最基本的原理是采用 React 的 createPortal 方法,在指定的元素下渲染子元素。可以理解为类似纯 js 的 getElementById('id').html(children(context))

相关推荐

  1. 关于 React 如何定义配置 HighCharts tooltip

    2023-12-09 00:40:04       34 阅读
  2. react中使用craco定义配置

    2023-12-09 00:40:04       38 阅读
  3. 如何写一个react定义的hooks?

    2023-12-09 00:40:04       23 阅读
  4. 如何React中创建定义Hooks

    2023-12-09 00:40:04       9 阅读
  5. ReactNative如何调用定义的原生模块

    2023-12-09 00:40:04       46 阅读
  6. react--定义列表字段

    2023-12-09 00:40:04       35 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-09 00:40:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-09 00:40:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-09 00:40:04       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-09 00:40:04       20 阅读

热门阅读

  1. CentOS 7 安装 Nginx

    2023-12-09 00:40:04       36 阅读
  2. 与脾气不太好的领导,相处原则和相处技巧分享

    2023-12-09 00:40:04       33 阅读
  3. flutter布局详解及代码示例(补充)

    2023-12-09 00:40:04       34 阅读
  4. MySQL 错误 1292 是什么?怎么解决?

    2023-12-09 00:40:04       38 阅读
  5. MySQL查看和修改时区

    2023-12-09 00:40:04       39 阅读
  6. 数据结构详解各种算法

    2023-12-09 00:40:04       35 阅读