vue3+echart

117 阅读1分钟

1:导入依赖

lib.ts

// lib.ts
import * as echarts from "echarts/core";

import {
  BarChart,
  LineChart,
  PieChart,
  MapChart,
  PictorialBarChart,
  RadarChart,
  ScatterChart,
} from "echarts/charts";

import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  PolarComponent,
  AriaComponent,
  ParallelComponent,
  LegendComponent,
  RadarComponent,
  ToolboxComponent,
  DataZoomComponent,
  VisualMapComponent,
  TimelineComponent,
  CalendarComponent,
  GraphicComponent,
} from "echarts/components";

echarts.use([
  LegendComponent,
  TitleComponent,
  TooltipComponent,
  GridComponent,
  PolarComponent,
  AriaComponent,
  ParallelComponent,
  BarChart,
  LineChart,
  PieChart,
  MapChart,
  RadarChart,
  PictorialBarChart,
  RadarComponent,
  ToolboxComponent,
  DataZoomComponent,
  VisualMapComponent,
  TimelineComponent,
  CalendarComponent,
  GraphicComponent,
  ScatterChart,
]);

export default echarts;

2:抽成hook

useEchart.ts

import { nextTick, onMounted, onUnmounted, Ref, unref } from "vue";
import type { EChartsOption } from "echarts";
import echarts from "@/util/lib";
import { SVGRenderer, CanvasRenderer } from "echarts/renderers";
enum RenderType {
  SVGRenderer = "SVGRenderer",
  CanvasRenderer = "CanvasRenderer",
}
enum ThemeType {
  Light = "light",
  Dark = "dark",
  Default = "default",
}


export default function useChart(
  elRef: Ref<HTMLElement>,
  autoChartSize = false,
  animation = false,
  render: RenderType = RenderType.SVGRenderer,
  theme: ThemeType = ThemeType.Default
) {
  // 渲染模式
  echarts.use(render === RenderType.SVGRenderer ? SVGRenderer : CanvasRenderer);
  // echart实例
  let chartInstance: echarts.ECharts | null = null;

  // 初始化echart
  const initCharts = () => {
    const el = unref(elRef);
    if (!el || !unref(el)) {
      return;
    }
    chartInstance = echarts.init(el, theme);
  };

  // 更新/设置配置
  const setOption = (option: EChartsOption) => {
    nextTick(() => {
      if (!chartInstance) {
        initCharts();
        if (!chartInstance) return;
      }

      chartInstance.setOption(option);
      hideLoading();
    });
  };

  // 获取echart实例
  function getInstance(): echarts.ECharts | null {
    if (!chartInstance) {
      initCharts();
    }
    return chartInstance;
  }

  // 更新大小
  function resize() {
    chartInstance?.resize();
  }

  // 监听元素大小
  function watchEl() {
    // 给元素添加过渡
    if (animation) {
      elRef.value.style.transition = "width 1s, height 1s";
    }
    const resizeObserver = new ResizeObserver((entries) => resize());
    resizeObserver.observe(elRef.value);
  }

  // 显示加载状
  function showLoading() {
    if (!chartInstance) {
      initCharts();
    }
    chartInstance?.showLoading();
  }
  // 显示加载状
  function hideLoading() {
    if (!chartInstance) {
      initCharts();
    }
    chartInstance?.hideLoading();
  }

  onMounted(() => {
    window.addEventListener("resize", resize);
    if (autoChartSize) watchEl();
  });

  onUnmounted(() => {
    window.removeEventListener("resize", resize);
  });

  return {
    setOption,
    getInstance,
    showLoading,
    hideLoading,
  };
}

3:使用

<template>
   <div ref="chartElPie" class="w-300 hp-100"></div>
</template>
<script lang="ts" setup>
import { onMounted, computed, nextTick, ref, Ref } from "vue";
import type { EChartsOption } from "echarts";
import useChart from "@/hooks/useChart";
    enum RenderType {
  SVGRenderer = "SVGRenderer",
  CanvasRenderer = "CanvasRenderer",
}
enum ThemeType {
  Light = "light",
  Dark = "dark",
  Default = "default",
}
const optionPie = computed<EChartsOption>(() => ({
  series: [
    {
      name: "按停车事件划分的车辆数",
      type: "pie",
      radius: ["40%", "70%"],
      color: ["#da70d6", "#32cd32", "#6495ed"],
      data: [
        { value: 10, name: "10%" },
        { value: 22, name: "22%" },
        { value: 68, name: "68%" },
      ],
    },
  ],
}));
    const { setOption: setOptionPie, showLoading: showLoadingPie } = useChart(
            chartElPie as Ref<HTMLElement>,
            true,
            true,
            RenderType.SVGRenderer,
            ThemeType.Light
            );
    onMounted(() => {
    nextTick(() => {
    showLoadingPie();
    setOptionPie(optionPie.value);
    });
    }); 
</script>