echarts不支持X轴标签自适应旋转角度?这个hooks解决你90%的问题!

200 阅读2分钟

echarts不支持X轴标签自适应旋转角度?这个hooks解决你90%的问题!

没什么写作才华,直接上图上代码

image.png

import { useCallback } from 'react';

const useLabelRotate = (antdTheme: any) => {
  const labelRotate = useCallback((chart, option) => {
    try {
      if (!chart || !option.xAxis) return;
      const axisModel = chart.getModel().getComponent('xAxis', 0);
      const labels = axisModel.axis.getViewLabels();

      // 获取容器宽度
      // const containerWidth = chart.getWidth();
      // 获取容器宽度并减去坐标轴的左右边距
      const containerAggregateWidth = chart.getWidth();
      const gridModel = chart.getModel().getComponent('grid', 0);
      const gridLeft = gridModel.get('left');
      const gridRight = gridModel.get('right');

      const leftPadding =
        typeof gridLeft === 'string' && gridLeft.endsWith('%')
          ? (parseFloat(gridLeft) / 100) * containerAggregateWidth
          : parseFloat(gridLeft || 0);

      const rightPadding =
        typeof gridRight === 'string' && gridRight.endsWith('%')
          ? (parseFloat(gridRight) / 100) * containerAggregateWidth
          : parseFloat(gridRight || 0);

      // 获取y轴的标签宽度
      const yAxisModel = chart.getModel().getComponent('yAxis', 0);
      const yAxisLabels = yAxisModel.axis.getViewLabels();

      // 获取 Y 轴标签字体样式(优先从 ECharts 配置中获取)
      const font = `12px ${antdTheme.fontFamily}`;

      const yAxisLabelWidth = yAxisLabels.reduce((max, label) => {
        const labelText = label.formattedLabel || label.rawLabel;
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        context!.font = font; // 假设字体为12px
        const textWidth = context!.measureText(labelText).width;
        return Math.max(max, textWidth);
      }, 0);

      const containerWidth = containerAggregateWidth - leftPadding - rightPadding - yAxisLabelWidth;
      if (!option.xAxis?.data?.length) {
        return;
      }

      // 获取标签数量
      const labelCount = option.xAxis?.data.length;

      // 获取最长标签的像素宽度
      const longestLabelWidth = labels.reduce((max, label) => {
        const labelText = label.formattedLabel || label.rawLabel;
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        context!.font = font; // 假设字体为12px
        const textWidth = context!.measureText(labelText).width;
        return Math.max(max, textWidth);
      }, 0);

      // 计算每个标签的可用宽度
      const availableWidth = containerWidth / labelCount;

      let rotate = 0;
      let interval = 0;

      // 如果可用宽度小于最长标签的宽度,旋转标签
      if (availableWidth < longestLabelWidth) {
        rotate = 45;
        // 看看斜着45度的标签是否会重叠
        if (availableWidth < longestLabelWidth * Math.cos(Math.PI / 4)) {
          rotate = 90;
          rotate = 90;
          // 90度旋转时,标签的高度就是最长标签的宽度
          if (containerWidth < longestLabelWidth) {
            // 如果容器宽度小于标签的高度(旋转后的宽度),就间隔显示
            interval = Math.ceil(labelCount / (containerWidth / 14));
          }
        }
      }

      // 设置图表的配置项和数据
      option.xAxis.axisLabel = {
        interval: interval,
        rotate: rotate,
      };

      chart.setOption(option);
    } catch (e) {
      console.error(e);
    }
  }, []);

  return labelRotate;
};

export default useLabelRotate;

报表来自一个AI驱动的数据库管理工具Chat2DB

让每个人在 Chat2DB都能轻松处理数据

如果有问题欢迎关注微信公众号Ch2DB,加群与我交流