vue中使用Echarts
引入
安装完Echarts包后,我们安装官网指示,使用按需导入。
文件:/src/plugin/echarts.ts
import type { App } from "vue";
import * as echarts from "echarts/core";
import { BarChart, LineChart } from "echarts/charts";
import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
import { UniversalTransition, LabelLayout } from "echarts/features";
import {
GridComponent,
TitleComponent,
DatasetComponent,
TransformComponent,
TooltipComponent,
} from "echarts/components";
import type {
// 系列类型的定义后缀都为 SeriesOption
BarSeriesOption,
LineSeriesOption,
} from "echarts/charts";
import type {
// 组件类型的定义后缀都为 ComponentOption
TitleComponentOption,
TooltipComponentOption,
GridComponentOption,
DatasetComponentOption,
} from "echarts/components";
import type { ComposeOption } from "echarts/core";
// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
export type ECOption = ComposeOption<
| BarSeriesOption
| LineSeriesOption
| TitleComponentOption
| TooltipComponentOption
| GridComponentOption
| DatasetComponentOption
>;
// 注册组件
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent,
BarChart,
LineChart,
LabelLayout,
UniversalTransition,
CanvasRenderer,
SVGRenderer,
]);
export function initEcharts(app: App) {
console.log("初始化echarts");
app.config.globalProperties.$echarts = echarts;
}
export default echarts;
编写基础Echarts组件
我们想要实现一个只需传入option的就可以重复复用的组件。
<template>
<div class="chart" style="width: 100%; height: 100%" ref="chartRef"></div>
</template>
<script setup lang="ts">
import { onMounted, ref, shallowRef, watch } from "vue";
import useEcharts, { type TEchartsOptions } from "../hook/useEchart";
import { useThemeHooks } from "../store/moudle/theme";
const props = defineProps<{
option: TEchartsOptions;
}>();
const themeColor = useThemeHooks();
const chartRef = ref<HTMLDivElement>();
const currentOption = shallowRef(props.option);
const { setOptions, initEcharts } = useEcharts(
chartRef,
currentOption.value,
true
);
// 监听options的变化。如果变化就重新设置options
watch(
() => props.option,
(newVal) => {
let targetOPtion: TEchartsOptions = {};
if (themeColor.theme && themeColor.theme.length > 0) {
targetOPtion = { ...newVal, color: themeColor.theme };
} else {
targetOPtion = { ...newVal };
}
setOptions(targetOPtion);
}
);
//监听主题变化。
watch(
() => themeColor.theme,
(newVal) => {
if (newVal && newVal.length > 0) {
setOptions({ color: newVal });
}
}
);
onMounted(() => {
initEcharts();
});
</script>
Hooks设计
import {
onDeactivated,
onMounted,
onUnmounted,
shallowRef,
type Ref,
} from "vue";
import echarts from "../plugins/echarts";
export type TEchartsOptions = echarts.EChartsCoreOption;
export default function useEcharts(
elRef: Ref<HTMLElement | undefined>,
option: TEchartsOptions,
isResize = false
) {
const myEcharts = shallowRef<echarts.ECharts>();
const initEcharts = (theme: string[] | null = null) => {
myEcharts.value = echarts.init(elRef.value, theme);
setOptions(option);
};
const setOptions = (options: TEchartsOptions) => {
options && myEcharts.value?.setOption(options);
};
const reSize = () => {
myEcharts.value?.resize();
};
onMounted(() => {
if (isResize) {
window.addEventListener("resize", reSize);
}
});
//如果页面keepLived,则需要移除resize事件
onDeactivated(() => {
window.removeEventListener("resize", reSize);
});
onUnmounted(() => {
myEcharts.value?.dispose();
});
return {
initEcharts,
setOptions,
reSize,
};
}
全局主题颜色变量
这里使用pinia库来实现全局变量
import { defineStore } from "pinia";
import { store } from "..";
import theme from "echarts/types/src/theme/dark.js";
const useThemeStore = defineStore("theme", {
state: () => {
return {
themeName: "vintage",
theme: [
"#d87c7c",
"#919e8b",
"#d7ab82",
"#6e7074",
"#61a0a8",
"#efa18d",
"#787464",
"#cc7e63",
"#724e58",
"#4b565b",
],
};
},
actions: {
changeTheme(theme: string[], name: string) {
this.theme = theme;
this.themeName = name;
},
},
});
export function useThemeHooks() {
return useThemeStore(store);
}
这里提供一些主要颜色
export const echartsThemeData = [
{
name: "vintage",
background: "#fef8ef",
theme: [
"#d87c7c",
"#919e8b",
"#d7ab82",
"#6e7074",
"#61a0a8",
"#efa18d",
"#787464",
"#cc7e63",
"#724e58",
"#4b565b",
],
},
{
name: "dark",
background: "#333",
theme: [
"#dd6b66",
"#759aa0",
"#e69d87",
"#8dc1a9",
"#ea7e53",
"#eedd78",
"#73a373",
"#73b9bc",
"#7289ab",
"#91ca8c",
"#f49f42",
],
},
{
name: "westeros",
background: "transparent",
theme: ["#516b91", "#59c4e6", "#edafda", "#93b7e3", "#a5e7f0", "#cbb0e3"],
},
{
name: "essos",
background: "rgba(242,234,191,0.15)",
theme: ["#893448", "#d95850", "#eb8146", "#ffb248", "#f2d643", "#ebdba4"],
},
{
name: "wonderland",
background: "transparent",
theme: ["#4ea397", "#22c3aa", "#7bd9a5", "#d0648a", "#f58db2", "#f2b3c9"],
},
{
name: "walden",
background: "rgba(252,252,252,0)",
theme: ["#3fb1e3", "#6be6c1", "#626c91", "#a0a7e6", "#c4ebad", "#96dee8"],
},
{
name: "chalk",
background: "#293441",
theme: [
"#fc97af",
"#87f7cf",
"#f7f494",
"#72ccff",
"#f7c5a0",
"#d4a4eb",
"#d2f5a6",
"#76f2f2",
],
},
{
name: "infographic",
background: "transparent",
theme: [
"#C1232B",
"#27727B",
"#FCCE10",
"#E87C25",
"#B5C334",
"#FE8463",
"#9BCA63",
"#FAD860",
"#F3A43B",
"#60C0DD",
"#D7504B",
"#C6E579",
"#F4E001",
"#F0805A",
"#26C0C0",
],
},
{
name: "macarons",
background: "transparent",
theme: [
"#2ec7c9",
"#b6a2de",
"#5ab1ef",
"#ffb980",
"#d87a80",
"#8d98b3",
"#e5cf0d",
"#97b552",
"#95706d",
"#dc69aa",
"#07a2a4",
"#9a7fd1",
"#588dd5",
"#f5994e",
"#c05050",
"#59678c",
"#c9ab00",
"#7eb00a",
"#6f5553",
"#c14089",
],
},
{
name: "roma",
background: "transparent",
theme: [
"#E01F54",
"#001852",
"#f5e8c8",
"#b8d2c7",
"#c6b38e",
"#a4d8c2",
"#f3d999",
"#d3758f",
"#dcc392",
"#2e4783",
"#82b6e9",
"#ff6347",
"#a092f1",
"#0a915d",
"#eaf889",
"#6699FF",
"#ff6666",
"#3cb371",
"#d5b158",
"#38b6b6",
],
},
{
name: "shine",
background: "transparent",
theme: [
"#c12e34",
"#e6b600",
"#0098d9",
"#2b821d",
"#005eaa",
"#339ca8",
"#cda819",
"#32a487",
],
},
{
name: "purple-passion",
background: "rgba(91,92,110,1)",
theme: ["#8a7ca8", "#e098c7", "#8fd3e8", "#71669e", "#cc70af", "#7cb4cc"],
},
];