Skip to content

[Bug]: 联动 tooltip 导致页面卡死 #2886

Open
@tzz-v

Description

@tzz-v

Describe the bug / 问题描述

给图表设置了联动 tooltip 后,再界面上用鼠标反复划过多个图表,一段时间后,界面就崩溃卡死了。

20250422-174813.mp4
const ChartCard: FC<IChartCard> = ({
  params,
  dateFrom,
  dateTo,
  chartMapRef
}) => {
  const { name, sourceData } = params;
  const {
    data: cardData,
    loading,
    error,
    run: queryData
  } = useQueryPrometheusData(sourceData ?? [], dateFrom, dateTo);
  useRefreshEvent(EventEmitterKey.Refresh_Real_Time_Market, queryData);

  const timeSet = useMemo(() => {
    if (!cardData?.length) {
      return [];
    }
    const set = new Set<number>();
    cardData.forEach((item) => {
      set.add(item.time);
    });
    return Array.from(set.values());
  }, [cardData]);

  const showTooltip = (time?: number) => {
    chartMapRef.current?.forEach((chart) => {
      chart.emit('tooltip:show', {
        data: { data: { x: time } }
      });
    });
  };

  const hideTooltip = () => {
    chartMapRef.current?.forEach((chart) => {
      chart.emit('tooltip:hide');
    });
  };

  return (
    <CardWrapper
      apiLoading={loading}
      apiError={
        error && (
          <Typography.Paragraph
            type="danger"
            ellipsis={{ rows: 2, tooltip: getErrorMessage(error ?? '') }}
          >
            {getErrorMessage(error ?? '')}
          </Typography.Paragraph>
        )
      }
      title={name}
      headBordered={false}
      className="chart-card-wrapper"
      emptyStatus={!cardData?.length}
      height={320}
    >
      <Line
        data={cardData}
        xField="time"
        yField="value"
        colorField="type"
        shapeField="smooth"
        height={280}
        marginLeft={0}
        marginRight={0}
        legend={false}
        area={{ style: { opacity: 0.2 } }}
        style={{ opacity: 0.6, lineWidth: 2 }}
        axis={{
          y: {
            tick: false,
            labelFormatter: (val: number) => {
              return renderValue(val, sourceData?.[0].unit);
            }
          },
          x: {
            line: true,
            lineStroke: 'gray',
            tickStroke: 'gray',
            labelAutoRotate: false,
            labelAutoHide: true,
            labelFormatter: (t: number) => moment(t).format('MM/DD HH:mm')
          }
        }}
        tooltip={{
          title: (d) => moment(d.time).format(dateDefaultFormat),
          items: [
            (d) => {
              return {
                name: d.type,
                value: renderValue(d.value, d.unit)
              };
            }
          ]
        }}
        interaction={{
          tooltip: {
            render: (
              _: any,
              {
                title,
                items
              }: {
                title: string;
                items: { name: string; value: string; color: string }[];
              }
            ) => {
              // 图表库bug:会出现重复的值,需要手动去重一下
              const map = new Map();
              items.forEach((item: any) => {
                map.set(item.name, item);
              });
              const liStr = Array.from(map.values())
                .map((item) => {
                  return `<div style="display: flex;justify-content: space-between;align-items: center;white-space: nowrap; line-height: 2em;">
                    <div style="display: flex; align-items: center; max-width: 216px;"><span style="background: ${item.color};width:8px;height:8px;display: inline-block; border-radius: 50%; margin-right:4px"></span><span style="flex: 1 1 0%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">${item.name}:</span></div>
                    <div style="display: inline-block; float: right; flex: 1 1 0%; text-align: right; min-width: 28px; margin-left: 30px; color: rgba(0, 0, 0, 0.85); overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">${item.value}</div>
                  </div>`;
                })
                .join('');
              return `<div>
                <div>${title}</div>
                <div>${liStr}</div>
              </div>`;
            }
          }
        }}
        onReady={({ chart }) => {
          chartMapRef.current?.push(chart);
          chart.on('plot:pointermove', (evt: any) => {
            const { x } = evt;
            const { layout } = chart.getView();
            const paddingLeft = layout.width - layout.innerWidth;
            const coordinatesX = x - paddingLeft;
            // 根据位置粗略计算出 tooltip data
            const percent = coordinatesX / layout.innerWidth;
            showTooltip(timeSet?.[Math.floor(percent * timeSet.length)] ?? 0);
          });
          chart.on('plot:pointerout', hideTooltip);
        }}
      />
    </CardWrapper>
  );
};

Reproduction link / 复现链接

No response

Steps to Reproduce the Bug or Issue / 重现步骤

No response

Version / 版本

Please select / 请选择

OS / 操作系统

  • macOS
  • Windows
  • Linux
  • Others / 其他

Browser / 浏览器

  • Chrome
  • Edge
  • Firefox
  • Safari (Limited support / 有限支持)
  • IE (Nonsupport / 不支持)
  • Others / 其他

Metadata

Metadata

Assignees

No one assigned

    Labels

    waiting for maintainerTriage or intervention needed from a maintainer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions