Custom Chart 自定义图表
@lark-ui/core

自定义图表

import { Chart } from "@lark-ui/core";
import * as echarts from "echarts/core";
import { EChartsOption } from "echarts";
import { useMemo } from "react";
import { useIsDarkMode } from "~/lib/use-is-dark-mode";

export function PieChartDemo() {
  const isDarkMode = useIsDarkMode();

  const options = useMemo<EChartsOption>(
    () => ({
      animation: true,
      animationDuration: 2000,
      tooltip: {
        show: true,
      },
      series: [
        {
          type: "pie",
          data: [
            { value: 101, name: "系列 A" },
            { value: 202, name: "系列 B" },
            { value: 303, name: "系列 C" },
            { value: 404, name: "系列 D" },
            { value: 505, name: "系列 E" },
          ],
        },
      ],
    }),
    [],
  );

  return (
    <Chart
      echarts={echarts}
      options={options}
      height={400}
      isDarkMode={isDarkMode}
    />
  );
}

使用 HTML 的自定义工具提示

对于需要自定义 HTML 格式的工具提示(Tooltip),请使用 dangerousHtmlFormatter 属性而不是标准的 formatter。这样可以让安全影响更加明确。

使用 dangerousHtmlFormatter 时,强烈建议使用 echarts.format.encodeHTML 对用户提供的任何内容进行净化处理,以防止 XSS 漏洞。

import { Chart } from "@lark-ui/core";
import * as echarts from "echarts/core";
import { EChartsOption } from "echarts";
import { useMemo } from "react";
import { useIsDarkMode } from "~/lib/use-is-dark-mode";

/**
 * 使用 dangerousHtmlFormatter 的 HTML 工具提示自定义图表。
 * 谨慎使用:dangerousHtmlFormatter 仅可用于可信的 HTML 内容。
 * 请始终使用 echarts.format.encodeHTML 或类似工具对用户提供的数据进行转义,
 * 以防止 XSS 漏洞。
 */
export function CustomTooltipChartDemo() {
  const isDarkMode = useIsDarkMode();

  const options = useMemo<EChartsOption>(
    () => ({
      tooltip: {
        trigger: "item",
        formatter: (params: any) => {
          // 重要:把所有动态值都用 echarts/format 的 encodeHTML 转义后再放进 HTML。
          // 这样可以防止恶意数据引发的 XSS 攻击,例如:
          // { name: "<img src=x onerror=alert('xss')>", value: "..." }
          const safeName = echarts.format.encodeHTML(params.name);
          const safeValue = echarts.format.encodeHTML(String(params.value));
          const safePercent = echarts.format.encodeHTML(
            String(Math.round(params.percent)),
          );

          return `
            <div style="padding: 8px;">
              <div style="font-weight: 600; margin-bottom: 4px;">${safeName}</div>
              <div>数值:<strong>${safeValue}</strong></div>
              <div style="font-size: 12px; opacity: 0.7; margin-top: 4px;">
                占总量的 ${safePercent}%
              </div>
            </div>
          `;
        },
      },
      series: [
        {
          type: "pie",
          data: [
            { value: 101, name: "系列 A" },
            { value: 202, name: "系列 B" },
            // 恶意系列名,用于演示 encodeHTML 提供的 XSS 防护。
            // 不做编码时它会弹出一个 alert;使用 encodeHTML 后只会安全地显示为纯文本。
            { value: 150, name: "<img src=x onerror=alert('XSS')>" },
            { value: 303, name: "系列 C" },
            { value: 404, name: "系列 D" },
          ],
        },
      ],
    }),
    [],
  );

  return (
    <Chart
      echarts={echarts}
      options={options}
      height={400}
      isDarkMode={isDarkMode}
    />
  );
}