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>