1.封装 echarts 组件
1.安装 echarts 所需 npm 包,如下。
npm i [email protected]
npm i [email protected] //社区图等
npm i @vueuse/[email protected] //一些好用的hook
2.封装 echarts 组件
1.在 component 目录下新建 Echarts 文件夹
2.在Echarts 文件夹下新建 config 文件夹(按需引入 echarts)
3.config 文件夹新建 index.ts 文件,配置如下
import * as echarts from 'echarts/core';
import { BarChart, LineChart, LinesChart, PieChart, ScatterChart, RadarChart, GaugeChart } from 'echarts/charts';
import {
TitleComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent,
LegendComponent,
PolarComponent,
GeoComponent,
ToolboxComponent,
DataZoomComponent,
} from 'echarts/components';
import { LabelLayout, UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';
import 'echarts-liquidfill';
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent,
LegendComponent,
PolarComponent,
GeoComponent,
ToolboxComponent,
DataZoomComponent,
BarChart,
LineChart,
LinesChart,
PieChart,
ScatterChart,
RadarChart,
GaugeChart,
LabelLayout,
UniversalTransition,
CanvasRenderer,
]);
export default echarts;
4.在 Echarts 目录下,新建 index.vue 文件,封装如下
<template>
<div id="echarts" ref="chartRef" :style="echartsStyle" />
</template>
<script setup lang="ts" name="ECharts">
import { ref, onMounted, onBeforeUnmount, watch, computed, markRaw, nextTick } from "vue";
import echarts from "./config";
import { useDebounceFn } from "@vueuse/core";
interface Props {
option: any;
renderer?: "canvas" | "svg";
resize?: boolean;
theme?: Object | string;
width?: number | string;
height?: number | string;
onClick?: (event: any) => any;
}
const props = withDefaults(defineProps<Props>(), {
renderer: "canvas",
resize: true
});
const echartsStyle = computed(() => {
return props.width || props.height
? { height: props.height + "px", width: props.width + "px" }
: { height: "100%", width: "100%" };
});
const chartRef = ref<HTMLDivElement | HTMLCanvasElement>();
const chartInstance = ref();
const draw = () => {
if (chartInstance.value) {
chartInstance.value.setOption(props.option, { notMerge: true });
}
};
watch(props, () => {
draw();
});
const handleClick = (event: any) => props.onClick && props.onClick(event);
const init = () => {
if (!chartRef.value) return;
chartInstance.value = echarts.getInstanceByDom(chartRef.value);
if (!chartInstance.value) {
chartInstance.value = markRaw(
echarts.init(chartRef.value, props.theme, {
renderer: props.renderer
})
);
chartInstance.value.on("click", handleClick);
draw();
}
};
const resize = () => {
if (chartInstance.value && props.resize) {
chartInstance.value.resize({ animation: { duration: 300 } });
}
};
const debouncedResize = useDebounceFn(resize, 300, { maxWait: 800 });
onMounted(() => {
nextTick(() => init());
window.addEventListener("resize", debouncedResize);
});
onBeforeUnmount(() => {
chartInstance.value?.dispose();
window.removeEventListener("resize", debouncedResize);
});
defineExpose({
getInstance: () => chartInstance.value,
resize,
draw
});
</script>
3.如何使用(任何新建 index.vue)
<template>
<div class="echarts">
<ECharts :option="option" :resize="false" />
</div>
</template>
<script setup lang="ts">
import ECharts from '@/components/ECharts/index.vue';
const option = {
title: [
{
text: (0.5 * 100).toFixed(0) + '%',
left: '49%',
top: '35%',
textAlign: 'center',
textStyle: {
fontSize: '16',
fontWeight: 'normal',
color: '#ffffff',
align: 'center',
textBorderColor: 'rgba(0, 0, 0, 0)',
textShadowColor: '#000',
textShadowBlur: 0,
textShadowOffsetX: 0,
textShadowOffsetY: 1,
},
},
{
text: '预约量',
left: '49%',
top: '25%',
textAlign: 'center',
textStyle: {
fontSize: '15',
fontWeight: 'normal',
color: '#ffffff',
align: 'center',
textBorderColor: 'rgba(0, 0, 0, 0)',
textShadowColor: '#000',
textShadowBlur: 0,
textShadowOffsetX: 0,
textShadowOffsetY: 1,
},
},
],
grid: {
top: '0',
left: '0px',
right: '0px',
bottom: '0',
containLabel: true,
},
polar: {
radius: ['75%', '85%'],
center: ['50%', '50%'],
},
angleAxis: {
max: 120,
clockwise: false,
axisLine: {
show: false,
},
axisTick: {
show: false,
},
axisLabel: {
show: false,
},
splitLine: {
show: false,
},
startAngle: 188,
},
radiusAxis: {
type: 'category',
show: true,
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
series: [
{
type: 'liquidFill',
radius: '70%',
z: 2,
center: ['50%', '50%'],
data: [0.4, 0.4, 0.4],
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: '#35FAB6' },
{ offset: 1, color: 'rgba(40, 209, 247,0.3)' },
],
global: false,
},
},
outline: {
borderDistance: 0,
itemStyle: {
borderWidth: 2,
borderColor: '#31d8d5',
shadowBlur: 20,
shadowColor: '#50c1a7',
},
},
label: {
show: false,
},
backgroundStyle: {
borderWidth: 1,
color: {
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.5,
colorStops: [
{ offset: 0, color: '#0D2648' },
{ offset: 0.8, color: '#0D2648' },
{ offset: 1, color: '#228E7D' },
],
global: false,
},
},
},
{
type: 'pie',
radius: ['80%', '80%'],
center: ['50%', '50%'],
z: 1,
label: { show: false },
silent: true,
itemStyle: {
borderWidth: 2,
borderType: [8, 10],
borderDashOffset: 15,
borderColor: '#31d8d5',
color: '#11144e',
borderCap: 'round',
},
data: [100],
},
{
type: 'bar',
data: [55],
z: 10,
coordinateSystem: 'polar',
roundCap: true,
color: '#31d8d5',
},
],
};
</script>
<style lang="less" scoped>
.echarts {
width: 100%;
height: calc(100% - 50px);
}
</style>
标签:false,color,vue3,value,props,chartInstance,echarts,vite
From: https://www.cnblogs.com/songkomei/p/18047394