近期我負(fù)責(zé)的公司人力資源系統(tǒng)中,薪酬統(tǒng)計(jì)模塊的開發(fā)進(jìn)度正穩(wěn)步推進(jìn)。在此過程中,我發(fā)現(xiàn)需要展示多種圖表(如 ECharts)來直觀反映數(shù)據(jù)。然而,ECharts 的配置過程相對復(fù)雜,頻繁查閱官方文檔不僅耗時(shí),而且效率不高。為了提升開發(fā)效率,我萌生了這樣一個(gè)想法:將 ECharts 中的一些通用屬性進(jìn)行提煉和整理,同時(shí)匯總常用的配置項(xiàng)以及在實(shí)際應(yīng)用中需要注意的要點(diǎn)。這樣一來,不僅能夠簡化配置過程,還能為團(tuán)隊(duì)提供一個(gè)便捷的參考指南。
EChart 資源
Vue-EChart
不想封裝 Echart, 可以選用這種方案。
Vue-ECharts 是一個(gè) Vue 組件,旨在簡化在 Vue 應(yīng)用中集成 ECharts 的過程。它封裝了 ECharts 的初始化和使用邏輯,用戶只需要在 Vue 模板中添加組件并傳遞相應(yīng)的 props,即可輕松創(chuàng)建圖表。
支持Vue2 & Vue3 & Nuxt3
DOC: https://github.com/ecomfe/vue-echarts#readme

優(yōu)點(diǎn):
- Vue-ECharts 組件會自動處理 ECharts 實(shí)例的生命周期,能夠根據(jù) Vue 組件的狀態(tài)變化自動更新圖表。這使得代碼更加簡潔,易于維護(hù)。
- 通過 Vue 的數(shù)據(jù)綁定機(jī)制,可以直接將數(shù)據(jù)綁定到組件的 props 上,Vue-ECharts 會自動將數(shù)據(jù)變化應(yīng)用到圖表上。
- 作為 Vue 組件,可以很容易地與其他 Vue 組件組合,并且可以利用 Vue 的指令和事件系統(tǒng)。
EChart 配置生成 option
目前只有三種圖表狀態(tài),可生成圖片和JSON.
https://github.com/BruceHenry/chart-creator

EChart 速查手冊 [官網(wǎng)]
https://echarts.apache.org/zh/cheat-sheet.html

EChart 主題配置 [官網(wǎng)]
https://echarts.apache.org/zh/theme-builder.html

EChart 社區(qū)示例 [社區(qū),提供了大量的示例基本可以滿足任何需求]
- MCChart

- isqqw

- MakeAPie

- PPChart

閱讀導(dǎo)圖

常用屬性配置
title 標(biāo)題配置

- text - 標(biāo)題文本,例如 "柱狀圖"
- subtext- 副標(biāo)題文本***
- *left 標(biāo)題的水平位置,可以是像'left' 'center' 'right' 或者像'20%' 這樣的百分比
- top*** **- 標(biāo)題的垂直位置,可以是像** **'top',**** __'middle'__,__** __'bottom'__** __或者像**__** __'20%'__ __這樣的百分比***
- textStyle*** **- 控制標(biāo)題文本樣式的對象,可以包括** ****color****,fontStyle,fontWeight,fontFamily,*fontSize****** ****等
- subtextStyle*** **- 控制副標(biāo)題文本樣式的對象,屬性同** ****textStyle*
- textAlign*** **- 標(biāo)題文本對齊,例如** **'left',**** __'right'__,**__** __'center'***
- padding*** **- 標(biāo)題內(nèi)邊距,可以是數(shù)字或數(shù)組** ****[上, 右, 下, 左]*
- itemGap - 主副標(biāo)題之間的間距
option = {
title: {
text: '主標(biāo)題文本',
subtext: '副標(biāo)題文本',
left: 'center',
top: 'top',
textStyle: {
color: 'black',
fontStyle: 'normal',
fontWeight: 'bold',
fontFamily: 'Arial',
fontSize: 18,
},
subtextStyle: {
color: '#aaa',
fontStyle: 'normal',
fontWeight: 'normal',
fontFamily: 'Arial',
fontSize: 12,
},
textAlign: 'center',
padding: [5, 10],
itemGap: 10
},
};
- formatter - 提示框浮層的內(nèi)容格式器,支持字符串模板和回調(diào)函數(shù)兩種形式
- axisPointer - 坐標(biāo)軸指示器配置,指定其類型如 'line'、'shadow' 等
- show - 是否顯示提示框組件,包括提示框浮層和 axisPointer,默認(rèn)為*** ***true
- backgroundColor - 提示框浮層的背景顏色
- borderColor - 提示框浮層的邊框顏色
- borderWidth - 提示框浮層的邊框?qū)?/font>
- padding - 提示框浮層內(nèi)邊距,可以是數(shù)字或數(shù)組 __[上, 右, 下, 左]**
tooltip: {
trigger: 'axis',
formatter: function (params) {
let res = params[0].name + '<br>';
params.forEach(function (item) {
res += item.seriesName + ': ' + item.value + '<br>';
});
return res;
},
axisPointer: {
type: 'shadow'
},
show: true,
backgroundColor: 'rgba(50,50,50,0.7)',
borderColor: '#333',
- formatter - 提示框浮層的內(nèi)容格式器,支持字符串模板和回調(diào)函數(shù)兩種形式
- axisPointer - 坐標(biāo)軸指示器配置,指定其類型如 'line'、'shadow' 等
- show - 是否顯示提示框組件,包括提示框浮層和 axisPointer,默認(rèn)為*** ***true
- backgroundColor - 提示框浮層的背景顏色
- borderColor - 提示框浮層的邊框顏色
- borderWidth - 提示框浮層的邊框?qū)?/font>
- padding - 提示框浮層內(nèi)邊距,可以是數(shù)字或數(shù)組 __[上, 右, 下, 左]**
tooltip: {
trigger: 'axis',
formatter: function (params) {
let res = params[0].name + '<br>';
params.forEach(function (item) {
res += item.seriesName + ': ' + item.value + '<br>';
});
return res;
},
axisPointer: {
type: 'shadow'
},
show: true,
backgroundColor: 'rgba(50,50,50,0.7)',
borderColor: '#333',
legend(圖例組件)

圖表的圖例,表示不同系列的標(biāo)識。
legend: {
top: '5%',
left: 'center',
data: ['直接訪問', '聯(lián)盟廣告', '搜索引擎']
}
series(系列列表)

每個(gè) series 代表一組數(shù)據(jù)項(xiàng)的集合,對于餅圖配置的主要部分。
series 屬性及其可能的值包括:
- type: 'pie' // 必須設(shè)置為 'pie' 表示這是一個(gè)餅圖。
- radius: 半徑,可以是百分比或固定像素值,也可以是數(shù)組形式表示內(nèi)外半徑。
- center: Pie圖的中心位置。
- data: 數(shù)據(jù)項(xiàng)數(shù)組,每個(gè)數(shù)據(jù)項(xiàng)包括 value(數(shù)值)和 name(名稱)。
- stillShowZeroSum: 如果所有數(shù)據(jù)值都是0,是否顯示圖形。
- label: 用于設(shè)置數(shù)據(jù)標(biāo)簽,如是否顯示、位置、格式等。
series: [
{
name: '訪問來源',
type: 'pie',
radius: '50%',
center: ['50%', '50%'],
data: [
{value: 335, name: '直接訪問'},
{value: 234, name: '聯(lián)盟廣告'},
{value: 1548, name: '搜索引擎'}
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
stillShowZeroSum: true,
label: {
normal: {
show: true,
position: 'outside'
},
emphasis: {
show: true,
textStyle: {
fontSize: '30',
fontWeight: 'bold'
}
}
}
}
]

color (配色方案)

定義顏色數(shù)組,用于系列中每個(gè)扇形的默認(rèn)顏色:
- 示例:
<font style="color:rgb(46, 50, 56);">['#5470C6', '#91CC75', '#FAC858', '#EE6666']</font>
animation (動畫配置)

完整配置示例代碼
option = {
title: {
text: 'Pie Chart Example'
},
tooltip: {
trigger: 'item'
},
legend: {
top: '5%',
left: 'center',
data: ['Direct Visit', 'Union Ad', 'Search Engine']
},
toolbox: {
show: true,
feature: {
saveAsImage: {},
restore: {}
}
},
series: [
{
name: 'Access From',
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: [
{ value: 335, name: 'Direct Visit' },
{ value: 234, name: 'Union Ad' },
{ value: 1548, name: 'Search Engine' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
label: {
normal: {
show: true,
position: 'outside',
formatter: '{b}: {c} (eyww0yu%)'
},
emphasis: {
show: true,
textStyle: {
fontSize: '30',
fontWeight: 'bold'
}
}
}
}
]
};
EChart 在 Vue3 中實(shí)戰(zhàn)
const chart = ref(null);
const initChart = () => {
if (chart.value) {
const myChart = echarts.init(chart.value);
myChart.setOption(props.option);
}
};
watch(
() => props.option,
(newOption) => {
if (chart.value) {
const myChart = echarts.getInstanceByDom(chart.value);
myChart.setOption(newOption);
}
}
);
響應(yīng)式處理
圖表在窗口大小變化時(shí)能夠自動調(diào)整。可以使用 resize()
方法手動調(diào)整圖表大小,通常是在 updated
生命周期鉤子中調(diào)用。
const resizeChart = () => {
if (chart.value) {
const myChart = echarts.getInstanceByDom(chart.value);
myChart.resize();
}
};
onMounted(() => {
initChart();
window.addEventListener('resize', resizeChart);
});
動態(tài)數(shù)據(jù)更新
使用 Vue 的響應(yīng)式數(shù)據(jù)(如 ref
或 reactive
)配合 watch
,在數(shù)據(jù)變化時(shí)調(diào)用 chart.setOption()
重新渲染圖表。
const chartOption = ref({
title: { text: '實(shí)時(shí)數(shù)據(jù)' },
tooltip: { trigger: 'axis' },
xAxis: { data: ['1', '2', '3', '4', '5'] },
yAxis: {},
series: [{
name: '銷量',
type: 'line',
data: [120, 132, 101, 134, 90]
}]
});
watch(
() => props.option,
(newOption) => {
if (chartInstance.value) {
chartInstance.value.setOption(newOption);
}
},
{ deep: true }
);
chartOption.value.series[0].data.push(Math.random() * 100);
chartOption.value.xAxis.data.push(String(chartOption.value.xAxis.data.length + 1));
圖表容器大小自適應(yīng)
父容器尺寸發(fā)生變化時(shí),圖表可能不會自動調(diào)整大小。 我們可以通過 監(jiān)聽 resize
事件或使用 Vue 的響應(yīng)式布局方案,調(diào)用 chart.resize()
更新圖表尺寸。
const observer = new ResizeObserver(() => {
chartInstance.value?.resize();
});
observer.observe(containerElement);
國際化與多語言支持
圖表中包含的文案(如標(biāo)題、提示)需要支持多語言。 我們可以使用 Vue I18n 或其他國際化工具動態(tài)替換文本。
npm install vue-i18n
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const option = reactive({
title: { text: t('chart.title') },
});
ECharts 圖表導(dǎo)出
toolbox: {
feature: {
saveAsImage: { show: true },
},
};
性能優(yōu)化
銷毀 ECharts 實(shí)例
在組件銷毀時(shí),確保銷毀 ECharts 實(shí)例,防止內(nèi)存泄漏。
onBeforeUnmount(() => {
if (chart.value) {
const myChart = echarts.getInstanceByDom(chart.value);
myChart.dispose();
}
window.removeEventListener('resize', resizeChart);
});
大數(shù)據(jù)渲染性能優(yōu)化
數(shù)據(jù)量大時(shí),ECharts 的渲染可能會導(dǎo)致性能瓶頸。 我們可以通過以下三種方式來達(dá)到優(yōu)化作用
- 使用
**dataZoom**
: 允許用戶縮放數(shù)據(jù)區(qū)域,減少可視數(shù)據(jù)點(diǎn)。 - 啟用分片渲染:
series: [
{
type: 'line',
large: true,
largeThreshold: 4000,
},
];
- 降級動畫: 動態(tài)數(shù)據(jù)場景中禁用或簡化動畫。
animation: false,
progressive: 4000,
progressiveThreshold: 10000,
圖表配置項(xiàng)太長,分離配置項(xiàng)
配置項(xiàng)代碼過長,組件可讀性降低。我們可以將配置項(xiàng)提取到單獨(dú)的模塊,便于復(fù)用和維護(hù)。

EChart 知識點(diǎn)常考
如何初始化和銷毀 ECharts 實(shí)例?
echarts.init(dom)
初始化。chart.dispose()
銷毀實(shí)例,避免內(nèi)存泄漏。
ECharts 常見配置項(xiàng)有哪些?
title
, legend
, tooltip
, grid
, xAxis
, yAxis
, series
, toolbox
, dataZoom
。
動態(tài)數(shù)據(jù)更新
- 如何實(shí)現(xiàn)圖表數(shù)據(jù)的動態(tài)更新?
- 如何監(jiān)聽 `props` 變化并更新圖表配置?
性能優(yōu)化
- 大數(shù)據(jù)渲染場景如何優(yōu)化?
- 什么是 `progressive` 渲染模式?
圖表事件
- 如何捕獲圖表點(diǎn)擊、懸停事件并執(zhí)行對應(yīng)的業(yè)務(wù)邏輯?
如何處理數(shù)據(jù)較多導(dǎo)致渲染卡頓的情況?
- 使用數(shù)據(jù)分片渲染(
progressive
)。 - 禁用動畫。
- 使用
dataZoom
限制顯示范圍。
如何實(shí)現(xiàn)圖表導(dǎo)出功能?
使用 toolbox.feature.saveAsImage
或通過 chart.getDataURL()
獲取圖表數(shù)據(jù)并導(dǎo)出。
最后
通過對 ECharts 通用屬性的深入提煉與系統(tǒng)整理,以及常用配置項(xiàng)的歸納總結(jié),我們能夠迅速實(shí)現(xiàn)圖表的搭建與展示,極大地提升了開發(fā)效率。此外,借助豐富的 ECharts 資源和示例,我們基本上能夠滿足大部分業(yè)務(wù)場景的需求。這樣一來,我們不僅能夠更加快捷地實(shí)現(xiàn)功能需求,還能騰出更多寶貴的時(shí)間,專注于其他重要任務(wù)。
?轉(zhuǎn)自https://www.cnblogs.com/HaiJun-Aion/p/18569547
該文章在 2025/2/8 10:54:56 編輯過