vue开发可视化大屏必修--echarts封装hooks

echarts封装hooks

目录

  • 处理props参数:
    • convertSeries: 允许用户通过 props.convertSeries 自定义 series 配置。
    • convertXAxis: 允许用户通过 props.convertXAxis 自定义 xAxis 配置。
    • convertYxis: 允许用户通过 props.convertYxis 自定义 yAxis 配置。
    • convertData: 允许用户通过 props.convertData 自定义 seriesdata 数据。
    • convertlegend: 允许用户通过 props.convertlegend 自定义 legend 配置。
  • 宽高适配: 使用 countChartSize 函数根据窗口尺寸调整图表的宽高。

基础配置

  1. getBaseLegend: 返回图例的基本样式。
    const getBaseLegend = () => {
      return {
        bottom: 0,
        left: 0,
        orient: "vertical",
        itemWidth: 8,
        itemHeight: 8,
        textStyle: {
          color: "white",
        },
      };
    };
    
  2. getBaseSeries: 返回基础的饼图配置。
    export const getBaseSeries = () => {
      return {
        type: "pie",
        radius: ["50%", "70%"],
        width: 140,
        height: 140,
        label: {
          show: false,
          position: "bottom",
        },
        labelLine: {
          show: false,
        },
        data: [
          { value: 1048, name: "大型及以上餐饮>500m²" },
          { value: 735, name: "中型餐饮150m²<面积≤500m²" },
          { value: 580, name: "小微型餐饮≤150m²" },
        ],
      };
    };
    

useChart Hook

  1. useChart: 接受一个 props 参数,根据 props 动态生成ECharts的配置对象 options
    export const useChart = (props: any) => {
      const options = {
        tooltip: {
          trigger: "item",
          position: ["50%", "50%"],
          borderColor: "#9DC3EF",
          borderWidth: 1,
          backgroundColor: "rgba(16,21,35,0.8)",
          textStyle: {
            color: "white",
          },
        },
        color: ["#83BAFA", "#3768D8", "#15DED7", "#F1E49D", "#668DE3"],
        legend: getBaseLegend(),
        series: [getBaseSeries()],
        grid: {
          bottom: "20%",
          height: 90,
        },
      } as any;
    

自定义配置处理

  1. 重写Series配置: 根据 props.convertSeries,可以自定义图表的 series 配置。
    if (props.convertSeries) {
      if (props.multiple) {
        options.series = props.convertSeries();
      } else {
        options.series[0] = {
          ...getBaseSeries(),
          ...props.convertSeries(),
        };
      }
    }
    
  2. 重写x轴: 如果存在 props.convertXAxis,则使用该函数来生成 xAxis 配置。
    if (props.convertXAxis) {
      options.xAxis = props.convertXAxis();
    }
    
  3. 重写Y轴: 同样地,若存在 props.convertYxis,则生成 yAxis 配置。
    if (props.convertYxis) {
      options.yAxis = props.convertYxis();
    }
    
  4. 重写数据: 使用 props.convertData 函数来生成 series 的数据。
    if (props.convertData) {
      options.series[0].data = props.convertData();
    }
    
  5. 重写图例: 通过 props.convertlegend 可以自定义图例配置。
    if (props.convertlegend) {
      options.legend = {
        ...getBaseLegend(),
        ...props.convertlegend(),
      };
    }
    

宽高适配

  1. 适配宽高: 对于series中的每个图表项,通过 countChartSize 函数根据窗口尺寸进行宽高适配。
    if (options.series) {
      options.series.forEach((item: { width: number; height: number }) => {
        if (item.width && item.height) {
          const currentItem = cloneDeep(item);
          const { width, height } = countChartSize(
            currentItem.width,
            currentItem.height
          );
          item.width = width;
          item.height = height;
        }
      });
    }
    

计算图表宽高

  1. countChartSize: 计算图表在不同屏幕尺寸下的宽高。
    const countChartSize = (width: number, height: number) => {
      return {
        width: (window.innerWidth / 1920) * width,
        height: (window.innerHeight / 1080) * height,
      };
    };
    

返回最终配置

  1. 返回 ****options: 返回生成的图表配置对象。
    return options;
    };
    

通过 useChart hook,用户可以根据需求自定义图表的各个部分配置,并且可以适配不同的屏幕尺寸,使得图表配置变得更加灵活和易用。

完整代码:

import { cloneDeep } from "lodash";

/**
 * 获取默认的图例样式
 */
const getBaseLegend = () => {
  return {
    bottom: 0,
    left: 0,
    orient: "vertical",
    itemWidth: 8,
    itemHeight: 8,
    textStyle: {
      color: "white",
    },
  };
};

export const getBaseSeries = () => {
  return {
    type: "pie",
    radius: ["50%", "70%"],
    width: 140,
    height: 140,
    label: {
      show: false,
      position: "bottom",
    },
    labelLine: {
      show: false,
    },
    data: [
      { value: 1048, name: "大型及以上餐饮>500m²" },
      { value: 735, name: "中型餐饮150m²<面积≤500m²" },
      { value: 580, name: "小微型餐饮≤150m²" },
    ],
  };
};

export const useChart = (props: any) => {
  const options = {
    tooltip: {
      trigger: "item",
      position: ["50%", "50%"],
      borderColor: "#9DC3EF",
      borderWidth: 1,
      backgroundColor: "rgba(16,21,35,0.8)",
      textStyle: {
        color: "white",
      },
    },
    color: ["#83BAFA", "#3768D8", "#15DED7", "#F1E49D", "#668DE3"],
    legend: getBaseLegend(),
    series: [getBaseSeries()],
    grid: {
      bottom: "20%",
      height: 90,
    },
  } as any;

  /** 抽象出每个选项的实现操作 */

  // 重写Series配置
  if (props.convertSeries) {
    // 图表里存在多个图
    if (props.multiple) {
      options.series = props.convertSeries();
    } else {
      // 只第一个图
      options.series[0] = {
        ...getBaseSeries(),
        ...props.convertSeries(),
      };
    }
  }

  // 重写x轴
  if (props.convertXAxis) {
    options.xAxis = props.convertXAxis();
  }

  // 重写Y轴
  if (props.convertYxis) {
    options.yAxis = props.convertYxis();
  }

  // 注意要先修改series 在修改数据 否则会被覆盖

  // 重写数据层
  if (props.convertData) {
    options.series[0].data = props.convertData();
  }

  // 重写图例
  if (props.convertlegend) {
    options.legend = {
      ...getBaseLegend(),
      ...props.convertlegend(),
    };
  }

  // 统一对宽高做适配
  if (options.series) {
    options.series.forEach((item: { width: number; height: number }) => {
      if (item.width && item.height) {
        const currentItem = cloneDeep(item);
        const { width, height } = countChartSize(
          currentItem.width,
          currentItem.height
        );
        item.width = width;
        item.height = height;
      }
    });
  }

  return options;
};

// 计算图表宽高
const countChartSize = (width: number, height: number) => {
  return {
    width: (window.innerWidth / 1920) * width,
    height: (window.innerHeight / 1080) * height,
  };
};

对封装echarts的使用

示例:社会餐饮图表配置
const societyChartOption = useChart({
  convertData: () => {
    return [
      { value: 1048, name: "大型及以上餐饮>500m²" },
      { value: 735, name: "中型餐饮150m²<面积≤500m²" },
      { value: 580, name: "小微型餐饮≤150m²" },
    ];
  },
});

这里调用 useChart 并传入一个对象,包含 convertData 方法。convertData 方法返回社会餐饮图表的数据。

示例:集体食堂图表配置
const groupChartOption = useChart({
  convertData: () => {
    return [
      { value: 1048, name: "学校食堂" },
      { value: 1048, name: "医疗机构食堂" },
      { value: 1048, name: "其他食堂" },
      { value: 1048, name: "养老机构食堂" },
    ];
  },
});

类似地,useChart 被调用并传入 convertData 方法来生成集体食堂图表的数据。

示例:认证企业数图表配置
const foodChartOptionA = useChart({
  convertData: () => {
    return [
      { value: 1048, name: "大型及以上餐饮>500m²" },
      { value: 735, name: "中型餐饮150m²<面积≤500m²" },
      { value: 580, name: "小微型餐饮≤150m²" },
      { value: 1048, name: "学校食堂" },
      { value: 1048, name: "医疗机构食堂" },
      { value: 1048, name: "其他食堂" },
      { value: 1048, name: "养老机构食堂" },
    ];
  },
  convertSeries: () => {
    return {
      with: 157,
      height: 157,
    };
  },
  convertlegend: () => {
    return {
      right: 0,
      left: null,
      itemGap: 25,
      top: "center",
    };
  },
});

这里 useChart 被调用时传入了三个方法:convertDataconvertSeriesconvertlegend。这些方法分别用来生成图表的数据、系列的宽高和图例的位置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mebius1916

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值