hello,大家好,我是程式設計師海軍,公眾號已經快一年多沒更新了,沒更新的這段時間,我去哪了呢。這兩年經歷了很多事情,主要情感上佔據大部分時間, 從失戀 - 談物件 - 再失戀。<br/><br/>
言歸正傳,近期我負責的公司人力資源系統中,薪酬統計模組的開發進度正穩步推進。在此過程中,我發現需要展示多種圖表(如 ECharts)來直觀反映資料。然而,ECharts 的配置過程相對複雜,頻繁查閱官方文件不僅耗時,而且效率不高。為了提升開發效率,我萌生了這樣一個想法:將 ECharts 中的一些通用屬性進行提煉和整理,同時彙總常用的配置項以及在實際應用中需要注意的要點。這樣一來,不僅能夠簡化配置過程,還能為團隊提供一個便捷的參考指南。
EChart 資源
Vue-EChart
不想封裝 Echart, 可以選用這種方案。
Vue-ECharts 是一個 Vue 元件,旨在簡化在 Vue 應用中整合 ECharts 的過程。它封裝了 ECharts 的初始化和使用邏輯,使用者只需要在 Vue 模板中新增元件並傳遞相應的 props,即可輕鬆建立圖表。</font>
支援Vue2 & Vue3 & Nuxt3
DOC: https://github.com/ecomfe/vue-echarts#readme
優點:
- Vue-ECharts 元件會自動處理 ECharts 例項的生命週期,能夠根據 Vue 元件的狀態變化自動更新圖表。這使得程式碼更加簡潔,易於維護。
- 透過 Vue 的資料繫結機制,可以直接將資料繫結到元件的 props 上,Vue-ECharts 會自動將資料變化應用到圖表上。
- 作為 Vue 元件,可以很容易地與其他 Vue 元件組合,並且可以利用 Vue 的指令和事件系統。
EChart 配置生成 option
目前只有三種圖表狀態,可生成圖片和JSON.
https://github.com/BruceHenry/chart-creator
EChart 速查手冊 [官網]
https://echarts.apache.org/zh/cheat-sheet.html
EChart 主題配置 [官網]
https://echarts.apache.org/zh/theme-builder.html
EChart 社群示例 [社群,提供了大量的示例基本可以滿足任何需求]
- MCChart
- isqqw
- MakeAPie
- PPChart
閱讀導圖
常用屬性配置
title 標題配置
- text - 標題文字,例如 "柱狀圖"
- subtext- 副標題文字***
- *left 標題的水平位置,可以是像'left' 'center' 'right' 或者像'20%' 這樣的百分比
- top*** **- 標題的垂直位置,可以是像<em>** **'top',<em>** \_\_'middle'\_\_,\_\_** \_\_'bottom'\_\_ \_\_或者像**\_\_** \_\_'20%'\_\_ \_\_**這樣的百分比***
- textStyle*** **- 控制標題文字樣式的物件,可以包括<em>** ****color****,fontStyle,fontWeight,fontFamily,*fontSize****** ****等<em>**
- subtextStyle*** **- 控制副標題文字樣式的物件,屬性同<em>** ****textStyle*
- textAlign*** **- 標題文字對齊,例如<em>** **'left',<em>** \_\_'right'\_\_,\_\_** \_\_**'center'***
- padding*** **- 標題內邊距,可以是數字或陣列<em>** ****[上, 右, 下, 左]*
- itemGap - 主副標題之間的間距
option = {
title: {
// 主標題文字設定
text: '主標題文字',
// 副標題文字設定
subtext: '副標題文字',
// 標題水平位置設定,'center' 表示居中
left: 'center',
// 標題垂直位置設定,'top' 表示頂部
top: 'top',
// 主標題樣式設定,包括文字顏色、字型風格、字型粗細、字型族、字型大小
textStyle: {
color: 'black', // 文字顏色
fontStyle: 'normal', // 字型風格,'normal'表示普通樣式
fontWeight: 'bold', // 字型粗細,'bold'表示加粗
fontFamily: 'Arial', // 字型族,這裡設定為Arial
fontSize: 18, // 字型大小,單位畫素
},
// 副標題樣式設定,屬性同主標題textStyle
subtextStyle: {
color: '#aaa', // 文字顏色
fontStyle: 'normal', // 字型風格
fontWeight: 'normal',// 字型粗細
fontFamily: 'Arial', // 字型族
fontSize: 12, // 字型大小
},
// 標題文字對齊方式,'center' 表示居中對齊
textAlign: 'center',
// 標題內邊距,第一個值表示上邊距,第二個值表示右邊距
padding: [5, 10],
// 主副標題之間的間距
itemGap: 10
},
// 此處省略其他的圖表配置選項…
};
tooltip 提示框
- <font style="color:rgb(46, 50, 56);">formatter</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 提示框浮層的內容格式器,支援字串模板和回撥函式兩種形式</font>
- <font style="color:rgb(46, 50, 56);">axisPointer</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 座標軸指示器配置,指定其型別如</font><font style="color:rgb(46, 50, 56);"> </font>'line'<font style="color:rgb(46, 50, 56);">、</font>'shadow'<font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">等</font>
- <font style="color:rgb(46, 50, 56);">show</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 是否顯示提示框元件,包括提示框浮層和 axisPointer,預設為</font>***<font style="color:rgb(46, 50, 56);"> </font>***true
- <font style="color:rgb(46, 50, 56);">backgroundColor</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 提示框浮層的背景顏色</font>
- <font style="color:rgb(46, 50, 56);">borderColor</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 提示框浮層的邊框顏色</font>
- <font style="color:rgb(46, 50, 56);">borderWidth</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 提示框浮層的邊框寬</font>
- <font style="color:rgb(46, 50, 56);">padding - 提示框浮層內邊距,可以是數字或陣列 </font>\_\_[上, 右, 下, 左]
// 工具提示配置
tooltip: {
// 觸發型別,'item' 表示資料項圖形觸發,用於散點圖等無類目軸的圖表,'axis' 表示座標軸觸發,用於柱狀圖等有類目軸的圖表
trigger: 'axis',
// 自定義提示框內容
formatter: function (params) {
// `params` 是一個陣列,包含了當前滑鼠所在點的所有資料資訊
let res = params[0].name + '<br>';
params.forEach(function (item) {
// 新增資訊,這裡只是個簡單示例,具體格式可以自由配置
res += item.seriesName + ': ' + item.value + '<br>';
});
return res;
},
// 座標軸指示器配置
axisPointer: {
type: 'shadow' // 'line' 表示直線指示器,'shadow' 表示陰影指示器
},
// 控制浮層顯示
show: true,
// 浮層背景顏色
backgroundColor: 'rgba(50,50,50,0.7)',
// 浮層邊框顏色
borderColor: '#333',
// 浮層邊框寬度
borderWidth: 0,
// 浮層內邊距
padding: 10 // 或者使用陣列形式,例如 [5, 10, 5, 10]
},
<font style="color:rgb(46, 50, 56);"></font>
<font style="color:rgb(46, 50, 56);"></font>
- <font style="color:rgb(46, 50, 56);">formatter</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 提示框浮層的內容格式器,支援字串模板和回撥函式兩種形式</font>
- <font style="color:rgb(46, 50, 56);">axisPointer</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 座標軸指示器配置,指定其型別如</font><font style="color:rgb(46, 50, 56);"> </font>'line'<font style="color:rgb(46, 50, 56);">、</font>'shadow'<font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">等</font>
- <font style="color:rgb(46, 50, 56);">show</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 是否顯示提示框元件,包括提示框浮層和 axisPointer,預設為</font>***<font style="color:rgb(46, 50, 56);"> </font>***true
- <font style="color:rgb(46, 50, 56);">backgroundColor</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 提示框浮層的背景顏色</font>
- <font style="color:rgb(46, 50, 56);">borderColor</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 提示框浮層的邊框顏色</font>
- <font style="color:rgb(46, 50, 56);">borderWidth</font><font style="color:rgb(46, 50, 56);"> </font><font style="color:rgb(46, 50, 56);">- 提示框浮層的邊框寬</font>
- <font style="color:rgb(46, 50, 56);">padding - 提示框浮層內邊距,可以是數字或陣列 </font>\_\_[上, 右, 下, 左]
// 工具提示配置
tooltip: {
// 觸發型別,'item' 表示資料項圖形觸發,用於散點圖等無類目軸的圖表,'axis' 表示座標軸觸發,用於柱狀圖等有類目軸的圖表
trigger: 'axis',
// 自定義提示框內容
formatter: function (params) {
// `params` 是一個陣列,包含了當前滑鼠所在點的所有資料資訊
let res = params[0].name + '<br>';
params.forEach(function (item) {
// 新增資訊,這裡只是個簡單示例,具體格式可以自由配置
res += item.seriesName + ': ' + item.value + '<br>';
});
return res;
},
// 座標軸指示器配置
axisPointer: {
type: 'shadow' // 'line' 表示直線指示器,'shadow' 表示陰影指示器
},
// 控制浮層顯示
show: true,
// 浮層背景顏色
backgroundColor: 'rgba(50,50,50,0.7)',
// 浮層邊框顏色
borderColor: '#333',
// 浮層邊框寬度
borderWidth: 0,
// 浮層內邊距
padding: 10 // 或者使用陣列形式,例如 [5, 10, 5, 10]
},
<font style="color:rgb(46, 50, 56);"></font>
<font style="color:rgb(46, 50, 56);"></font>
<font style="color:rgb(46, 50, 56);">legend(圖例元件)</font>
<font style="color:rgb(46, 50, 56);">圖表的圖例,表示不同系列的標識。</font>
legend: {
top: '5%',
left: 'center',
data: ['直接訪問', '聯盟廣告', '搜尋引擎']
}
<font style="color:rgb(46, 50, 56);"></font>
<font style="color:rgb(46, 50, 56);"></font>
<font style="color:rgb(46, 50, 56);">series(系列列表)</font>
<font style="color:rgb(46, 50, 56);">每個 </font>series<em><font style="color:rgb(46, 50, 56);"> 代表一組資料項的集合,對於餅圖配置的主要部分。</font>
<font style="color:rgb(46, 50, 56);">series 屬性及其可能的值包括:</font>
- <font style="color:rgb(46, 50, 56);">type: </font>'pie'<font style="color:rgb(46, 50, 56);"> // 必須設定為 'pie' 表示這是一個餅圖。</font>
- <font style="color:rgb(46, 50, 56);">radius: 半徑,可以是百分比或固定畫素值,也可以是陣列形式表示內外半徑。</font>
- <font style="color:rgb(46, 50, 56);">center: Pie圖的中心位置。</font>
- <font style="color:rgb(46, 50, 56);">data: 資料項陣列,每個資料項包括</font><font style="color:rgb(46, 50, 56);"> </font>value<font style="color:rgb(46, 50, 56);">(數值)和</font><font style="color:rgb(46, 50, 56);"> </font>name<font style="color:rgb(46, 50, 56);">(名稱)。</font>
- <font style="color:rgb(46, 50, 56);">stillShowZeroSum: 如果所有資料值都是0,是否顯示圖形。</font>
- <font style="color:rgb(46, 50, 56);">label: 用於設定資料標籤,如是否顯示、位置、格式等。</font>
<font style="color:rgb(46, 50, 56);"></font>
series: [
{
name: '訪問來源',
type: 'pie',
radius: '50%', // 半徑大小,支援百分比
center: ['50%', '50%'], // 餅圖的中心位置
data: [
{value: 335, name: '直接訪問'},
{value: 234, name: '聯盟廣告'},
{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'
}
}
}
}
]
toolbox<font style="color:rgb(46, 50, 56);"> (工具欄配置) </font>
color<font style="color:rgb(46, 50, 56);"> (配色方案) </font>
<font style="color:rgb(46, 50, 56);"> 定義顏色陣列,用於系列中每個扇形的預設顏色:</font>
- <font style="color:rgb(46, 50, 56);">示例:</font>
<font style="color:rgb(46, 50, 56);">['#5470C6', '#91CC75', '#FAC858', '#EE6666']</font>
<font style="color:rgb(46, 50, 56);"></font>
<font style="color:rgb(46, 50, 56);"></font>
<font style="color:rgb(46, 50, 56);"></font>
animation<font style="color:rgb(46, 50, 56);"> (動畫配置) </font>
<font style="color:rgb(46, 50, 56);">完整配置示例程式碼</font>
option = {
title: {
// 餅圖的標題
text: 'Pie Chart Example'
},
tooltip: {
// 滑鼠懸浮時的提示框設定
trigger: 'item' // item: 資料項圖形觸發
},
legend: {
// 圖例元件,展示不同系列的標識顏色和名稱
top: '5%', // 距離容器上方的距離
left: 'center', // 水平居中
// 對應系列名稱的資料
data: ['Direct Visit', 'Union Ad', 'Search Engine']
},
toolbox: {
show: true, // 顯示工具欄
feature: {
saveAsImage: {}, // 儲存為圖片功能
restore: {} // 還原功能
}
},
series: [
{
// 系列名稱,用於tooltip的顯示
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} ({d}%)'
},
emphasis: {
// 高亮狀態下的文字樣式定義
show: true,
textStyle: {
fontSize: '30', // 字型大小
fontWeight: 'bold' // 字型粗細
}
}
}
}
]
};
EChart 在 Vue3 中實戰
// 圖表例項的引用
const chart = ref(null);
// 初始化圖表
const initChart = () => {
if (chart.value) {
const myChart = echarts.init(chart.value); // 初始化 ECharts 例項
myChart.setOption(props.option); // 設定配置項
}
};
// 監聽 props 的變化,動態更新圖表
watch(
() => props.option,
(newOption) => {
if (chart.value) {
const myChart = echarts.getInstanceByDom(chart.value); // 獲取已初始化的圖表例項
myChart.setOption(newOption); // 更新配置項
}
}
);
響應式處理
圖表在視窗大小變化時能夠自動調整。可以使用 resize()
方法手動調整圖表大小,通常是在 updated
生命週期鉤子中呼叫。
// 響應式調整圖表大小, 監聽視窗大小變化,確保圖表自適應容器的大小。
const resizeChart = () => {
if (chart.value) {
const myChart = echarts.getInstanceByDom(chart.value);
myChart.resize(); // 調整圖表尺寸
}
};
// 生命週期鉤子
onMounted(() => {
initChart(); // 元件掛載後初始化圖表
window.addEventListener('resize', resizeChart); // 監聽視窗大小變化
});
動態資料更新
使用 Vue 的響應式資料(如 ref
或 reactive
)配合 watch
,在資料變化時呼叫 chart.setOption()
重新渲染圖表。
const chartOption = ref({
title: { text: '實時資料' },
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));
圖表容器大小自適應
父容器尺寸發生變化時,圖表可能不會自動調整大小。 我們可以透過 監聽 resize
事件或使用 Vue 的響應式佈局方案,呼叫 chart.resize()
更新圖表尺寸。
const observer = new ResizeObserver(() => {
chartInstance.value?.resize(); // 動態調整大小
});
observer.observe(containerElement); // 監聽容器
國際化與多語言支援
圖表中包含的文案(如標題、提示)需要支援多語言。 我們可以使用 Vue I18n 或其他國際化工具動態替換文字。
npm install vue-i18n
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const option = reactive({
title: { text: t('chart.title') },
});
ECharts 圖表匯出
toolbox: {
feature: {
saveAsImage: { show: true },
},
};
效能最佳化
銷燬 ECharts 例項
在元件銷燬時,確保銷燬 ECharts 例項,防止記憶體洩漏。
onBeforeUnmount(() => {
if (chart.value) {
const myChart = echarts.getInstanceByDom(chart.value);
myChart.dispose(); // 銷燬 ECharts 例項
}
window.removeEventListener('resize', resizeChart); // 移除事件監聽
});
大資料渲染效能最佳化
資料量大時,ECharts 的渲染可能會導致效能瓶頸。 我們可以透過以下三種方式來達到最佳化作用
- 使用
**dataZoom**
: 允許使用者縮放資料區域,減少可視資料點。 - 啟用分片渲染:
series: [
{
type: 'line',
large: true, // 啟用大資料最佳化
largeThreshold: 4000, // 資料量門檻
},
];
- 降級動畫: 動態資料場景中禁用或簡化動畫。
animation: false,
progressive: 4000, // 分步渲染
progressiveThreshold: 10000, // 資料點門檻
圖表配置項太長,分離配置項
配置項程式碼過長,元件可讀性降低。我們可以將配置項提取到單獨的模組,便於複用和維護。
EChart 知識點常考
如何初始化和銷燬 ECharts 例項?
echarts.init(dom)
初始化。chart.dispose()
銷燬例項,避免記憶體洩漏。
ECharts 常見配置項有哪些?
title
,legend
,tooltip
,grid
,xAxis
,yAxis
,series
,toolbox
,dataZoom
。
動態資料更新
- 如何實現圖表資料的動態更新?
- 如何監聽 `props` 變化並更新圖表配置?
效能最佳化
- 大資料渲染場景如何最佳化?
- 什麼是 `progressive` 渲染模式?
圖表事件
- 如何捕獲圖表點選、懸停事件並執行對應的業務邏輯?
如何處理資料較多導致渲染卡頓的情況?
- 使用資料分片渲染(
progressive
)。 - 禁用動畫。
- 使用
dataZoom
限制顯示範圍。
如何實現圖表匯出功能?
使用 toolbox.feature.saveAsImage
或透過 chart.getDataURL()
獲取圖表資料並匯出。
最後
透過對 ECharts 通用屬性的深入提煉與系統整理,以及常用配置項的歸納總結,我們能夠迅速實現圖表的搭建與展示,極大地提升了開發效率。此外,藉助豐富的 ECharts 資源和示例,我們基本上能夠滿足大部分業務場景的需求。這樣一來,我們不僅能夠更加快捷地實現功能需求,還能騰出更多寶貴的時間,專注於其他重要任務。 <br/><br/>
歡迎關注我的微信公眾號【前端自學社群】,在那裡我將分享更多關於前端技術的心得與實用技巧。