本文介绍: 当我们结合 React 使用 highCharts 库时,存在一些特殊自定义的情况,比如针对 Tooltip 定制样式。当然 highCharts 也提供了配置自定义 tooltipformatter 方法可以支持 html 元素。但是并不够灵活,对于配置复杂样式或组件复用情况下,并不友好。因此寻求新的思路,以下便是社区常用的一个方法,在此记录。该实现方式基本原理采用 React 的方法,在指定元素渲染子元素。

前言

我们结合 React 使用 highCharts 库时,存在一些特殊自定义的情况,比如针对 Tooltip 定制化样式。当然 highCharts 也提供了配置自定义 tooltipformatter 方法,可以支持 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 &amp;&amp; document.getElementById(generateTooltipId(chart.index));

  return node &amp;&amp; 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 方法,在指定的元素下渲染子元素。可以理解为类似纯 jsgetElementById('id').html(children(context))

原文地址:https://blog.csdn.net/GuoJiangweigege/article/details/134735506

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_23652.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注