前言:最近一个项目刚收工,分享一个常用的封装echarts的组件。
一、直接上组件代码
<template>
<el-card class="echart-card" shadow="hover">
<template v-slot:header>
<div class="card-header">
<div class="card-header-title">
<component
class="icon"
:is="headerIcon"
theme="filled"
size="16"
:strokeWidth="3"
fill="#333"
/>
<span :class="titleStyle === 'small' ? 'title' : 'titleBig'" style="fontWeight:'bold">{{
title
}}</span>
</div>
<div class="card-header-right">
<slot name="header-right"></slot>
</div>
</div>
</template>
<div class="echarts" ref="chartContainer" :id="`echarts${index}`" :style="style"></div>
</el-card>
</template>
<script setup>
import debounce from "lodash/debounce";
import {
onMounted,
ref,
reactive,
computed,
watch,
onBeforeUnmount,
nextTick,
} from "vue";
// import { useStore } from 'vuex';
// 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
import * as echarts from "echarts/core";
import { GraphicComponent } from "echarts/components";
// 引入柱状图图表,图表后缀都为 Chart
import theme from "./theme.json";
import {
BarChart,
CandlestickChart,
FunnelChart,
GaugeChart,
LineChart,
PieChart,
RadarChart,
ScatterChart,
GraphChart,
LinesChart,
TreemapChart
} from "echarts/charts";
// 引入提示框,标题,直角坐标系组件,组件后缀都为 Component
import {
TitleComponent,
TooltipComponent,
GridComponent,
LegendComponent,
ToolboxComponent,
MarkPointComponent,
MarkLineComponent,
} from "echarts/components";
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
import { CanvasRenderer } from "echarts/renderers";
// 注册必须的组件
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
BarChart,
LineChart,
PieChart,
RadarChart,
GaugeChart,
CandlestickChart,
ScatterChart,
CanvasRenderer,
LegendComponent,
ToolboxComponent,
MarkPointComponent,
MarkLineComponent,
FunnelChart,
GraphicComponent,
GraphChart,
LinesChart,
TreemapChart
]);
const props = defineProps({
// 图表下标 同个页面有多个图表时,必填
index: {
type: Number,
default: 0,
},
title: {
type: String,
default: "标题",
},
headerIcon: {
type: String,
default: "icon-full-screen",
},
style: {
type: Object,
default: () => {
return {
width: "100%",
height: "380px",
};
},
},
options: {
type: Object,
default: () => {
return {};
},
},
grid: {
type: Object,
default: () => {
return {
top: "10px",
left: 0,
right: "1px",
bottom: 0,
containLabel: true,
};
},
},
titleStyle: {
type: String,
default: "small",
},
});
let chart = null;
const chartContainer =ref(null)
let timer = ref(null);
//组件挂载完成后执行的钩子函数
onMounted(() => {
window.addEventListener(
"resize",
debounce(() => {
chart.resize(); //页面大小变化后Echarts也更改大小
}, 200)
);
});
//组件卸载之前执行的钩子函数
onBeforeUnmount(() => {
clearTimeout(timer);
timer = null;
});
const initChart = () => {
if(chartContainer.value){
if(chart){
chart.dispose()
}
echarts.registerTheme("wonderland", theme);
// chart = echarts.init(document.getElementById("echarts" + props.index), theme);
chart = echarts.init(chartContainer.value, theme);
// 绘制图表
chart.setOption({
grid: props.grid,
...props.options,
});
}
};
watch(
() => props.options, //监听
() => {
nextTick(() => {
initChart();
});
},
{
deep: true,
immediate: true,
}
);
</script>
<style lang="scss" scoped>
.echart-card {
border-radius: 10px;
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
&-title {
display: flex;
align-content: center;
align-items: center;
color: #606266;
.icon {
display: flex;
padding-right: 5px;
}
}
}
.echarts {
margin: 0 auto;
background-color: #928f8f;
}
}
</style>
二、theme.json统一风格
{
"color": ["#007FC6", "#00A0F9", "#2BC7E2", "#EA7C13", "#FFB56E", "#FFE8D1"],
"backgroundColor": "rgba(255,255,255,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#666666"
},
"subtextStyle": {
"color": "#999999"
}
},
"line": {
"itemStyle": {
"borderWidth": "2"
},
"lineStyle": {
"width": "3"
},
"symbolSize": "8",
"symbol": "emptyCircle",
"smooth": false
},
"radar": {
"itemStyle": {
"borderWidth": "2"
},
"lineStyle": {
"width": "3"
},
"symbolSize": "8",
"symbol": "emptyCircle",
"smooth": false
},
"bar": {
"itemStyle": {
"barBorderWidth": 0,
"barBorderColor": "#cccccc"
}
},
"pie": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#cccccc"
}
},
"scatter": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#cccccc"
}
},
"boxplot": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#cccccc"
}
},
"parallel": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#cccccc"
}
},
"sankey": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#cccccc"
}
},
"funnel": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#cccccc"
}
},
"gauge": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#cccccc"
}
},
"candlestick": {
"itemStyle": {
"color": "#84a2fe",
"color0": "transparent",
"borderColor": "#84a2fe",
"borderColor0": "#22c3aa",
"borderWidth": "1"
}
},
"graph": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#cccccc"
},
"lineStyle": {
"width": "1",
"color": "#cccccc"
},
"symbolSize": "8",
"symbol": "emptyCircle",
"smooth": false,
"color": ["#84a2fe", "#22c3aa", "#7bd9a5", "#d0648a", "#08a17e", "#f2b3c9"],
"label": {
"color": "#ffffff"
}
},
"map": {
"itemStyle": {
"areaColor": "#eeeeee",
"borderColor": "#999999",
"borderWidth": 0.5
},
"label": {
"color": "#28544e"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(34,195,170,0.25)",
"borderColor": "#22c3aa",
"borderWidth": 1
},
"label": {
"color": "#349e8e"
}
}
},
"geo": {
"itemStyle": {
"areaColor": "#eeeeee",
"borderColor": "#999999",
"borderWidth": 0.5
},
"label": {
"color": "#28544e"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(34,195,170,0.25)",
"borderColor": "#22c3aa",
"borderWidth": 1
},
"label": {
"color": "#349e8e"
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#999999"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#eeeeee"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#999999"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#eeeeee"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#999999"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#eeeeee"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#999999"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": ["#eeeeee"]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"]
}
}
},
"toolbox": {
"iconStyle": {
"borderColor": "#999999"
},
"emphasis": {
"iconStyle": {
"borderColor": "#666666"
}
}
},
"legend": {
"textStyle": {
"color": "#999999"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#cccccc",
"width": 1
},
"crossStyle": {
"color": "#cccccc",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#84a2fe",
"width": 1
},
"itemStyle": {
"color": "#84a2fe",
"borderWidth": 1
},
"controlStyle": {
"color": "#84a2fe",
"borderColor": "#84a2fe",
"borderWidth": 0.5
},
"checkpointStyle": {
"color": "#84a2fe",
"borderColor": "#3cebd2"
},
"label": {
"color": "#84a2fe"
},
"emphasis": {
"itemStyle": {
"color": "#84a2fe"
},
"controlStyle": {
"color": "#84a2fe",
"borderColor": "#84a2fe",
"borderWidth": 0.5
},
"label": {
"color": "#84a2fe"
}
}
},
"visualMap": {
"color": ["#d0648a", "#22c3aa", "#adfff1"]
},
"dataZoom": {
"backgroundColor": "rgba(255,255,255,0)",
"dataBackgroundColor": "rgba(222,222,222,1)",
"fillerColor": "rgba(114,230,212,0.25)",
"handleColor": "#cccccc",
"handleSize": "100%",
"textStyle": {
"color": "#999999"
}
},
"markPoint": {
"label": {
"color": "#ffffff"
},
"emphasis": {
"label": {
"color": "#ffffff"
}
}
}
}
可以直接将以上两个代码复制到组件文件夹里面
三、使用该组件
<EchartsCom
title="协议流量趋势图"
:index="11"
:titleStyle="'big'"
headerIcon="icon-chart-line"
:style="{ height: '250px' }"
:options="{
tooltip: trendSeries.tooltip,
series: trendSeries.series,
xAxis: trendSeries.xAxis,
yAxis: trendSeries.yAxis,
grid: trendSeries.grid,
}"
></EchartsCom>
可以很清楚的看到,其实主要就是传echarts的配置。
配置代码(就以折线图举例):
const trendSeries = ref({
grid: { top: '15%', bottom: '5%', left: '10%', right: '18%', containLabel: true },
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line',
},
},
series: {
type: 'line',
data: [120, 132, 101, 134, 90, 230, 210],
symbol: 'circle',
lineStyle: {
normal: {
color: '#008FFF',
},
},
symbolSize: 10,
itemStyle: {
normal: {
color: '#fff',
borderColor: '#008FFF',
},
borderRadius: [30, 30, 0, 0],
shadowColor: 'rgb(255,255,255)',
shadowBlur: 4,
},
smooth: false,
},
xAxis: {
name: '时间',
type: 'category',
data: [
'2024-04-18',
'2024-04-19',
'2024-04-20',
'2024-04-21',
'2024-04-22',
'2024-04-23',
'2024-04-24',
],
splitLine: {
show: false,
},
axisLabel: {
color: '#002745',
},
},
yAxis: {
name: '单位(次)',
type: 'value',
minInterval: 1,
splitLine: {
show: true,
lineStyle: {
width: 2,
type: 'dashed',
},
},
axisLine: {
show: false,
},
axisLabel: {
show: true,
formatter(v) {
v = v.toString();
if (v >= 100000000000) {
return v.substring(0, 5) / 10 + '亿';
} else if (v >= 10000000000) {
return v.substring(0, 4) / 10 + '亿';
} else if (v >= 1000000000) {
return v.substring(0, 3) / 10 + '亿';
} else if (v >= 100000000) {
return v.substring(0, 2) / 10 + '亿';
} else if (v >= 10000000) {
return v.substring(0, 4) + '万';
} else if (v >= 1000000) {
return v.substring(0, 3) + '万';
} else if (v >= 100000) {
return v.substring(0, 2) + '万';
} else if (v >= 10000) {
return v.substring(0, 2) / 10 + '万';
} else if (v >= 1000) {
return v;
} else {
return v;
}
},
},
},
});
效果展示:
如果想用饼图、柱状图之类的就可以直接传相应的配置即可,这样可以灵活控制每个图的不用样式。
之前我封装过几个组件都是把echarts的配置写进组件里面,但是后面发现如果一个页面需要七八个echarts图表,并且样式都是不一样的,那么就比较适用该文介绍的封装方法。