開發背景就不過多贅述了,直接先來幾張效果圖吧
1.首先在 package.json 中添加echarts:
{
"dependencies": {
"echarts": "^5.0.0",
}
}
2.然后執行 npm install;
3.接下來就開始編寫相關組件文件,代碼量較大,建議直接復制下來按步驟運行:
3.1.創建組件文件 barLineChartPY.vue 代碼如下:

<template> <!-- 多折線圖 圓滑轉折點 面積漸變色 --> <div style="with: 100%; height: 100%;" :id="id"></div> </template> <script> export default { props: { "id": { type: String, default: "myChart" }, "title": { type: String, default: "" }, "color": { type: String, default: "" }, "chartData": { type: Object, default: undefined }, "units": { type: String, default: "" }, "yMax": { type: Number, default: undefined } }, data() { return { myChart: {}, colors: ['#3769C9', '#EB9C06', '#80FFA5', '#00DDFF', '#FF0087'], xData: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'], // 柱狀圖的 基礎 series 本組件中的默認 series seriesBar: { name: '', type: 'bar', // barWidth: 10, // stack: 'total', // label: {show: false}, // itemStyle: { //這里設置柱形圖圓角 [左上角,右上角,右下角,左下角] // barBorderRadius: 30, // 柱狀圖 柱子 漸變色 或 單色 // 前4個參數用於配置漸變色的起止位置, 這4個參數依次對應右/下/左/上四個方位. 而0 0 0 1則代表漸變色從正上方開始 // offset的范圍是0 ~ 1, 用於表示位置 // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{offset: 0, color: '#033BFF'}, {offset: 1, color: '#01B1FF'}]) // }, // emphasis: { // focus: 'series', // itemStyle: { // 柱狀圖 柱子 漸變色 或 單色 // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{offset: 0, color: '#01B1FF'}, {offset: 1, color: '#033BFF'}]) // } // }, data: [123, 150, 100, 300, 500, 1000, 1300, 1100, 800, 600, 500, 350], data0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }, // 折線圖的 基礎 series seriesLine: { name: '', //this.chartData.seriesName, type: "line", // smooth: true, // 圓滑的拐點 默認false // showSymbol: true, data: [123, 150, 100, 300, 500, 1000, 1300, 1100, 800, 600, 500, 350], // this.chartData.dataArr, data0: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // lineStyle: { // color: "#00DDFF", // width: 1, // }, // areaStyle: { // color: "transparent", // 折線圖 面積 漸變色 或 單色 // color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{offset: 0, color: "#00DDFFFF"}, {offset: 1, color: "#00DDFF00"}]) // }, // emphasis: { // focus: 'series' // } } } }, methods: { initChart() { var echarts = require("echarts"); // 基於准備好的dom,初始化echarts實例 this.myChart = echarts.init(document.getElementById(this.id)); // 繪制圖表---橫軸標識--xAxis.data=['1月','2月','3月'] this.xData = this.chartData.xData && this.chartData.xData.length > 0 ? this.chartData.xData : this.xData; // debugger var flag = false; const units = this.units; const series = this.getSeries(); for (var ii = 0, nn = series.length; ii < nn; ii++) { if (series[ii].type == 'bar') { flag = true; break; } } var left = 45; if (this.yMax && (this.yMax + '').length <= 3) { left = 30; } else if (this.yMax && (this.yMax + '').length <= 4) { left = 40; } else if (this.yMax && (this.yMax + '').length <= 6) { left = 55; } var option = { grid: {top: "30", bottom: '25', right: '30', left: left}, tooltip: { trigger: "axis", formatter: function(params) { // 自定義 tooltip // console.log(params); var txt = params[0].name; for (var i = 0, n = params.length; i < n; i++) { var sn = params[i].seriesName, cl = params[i].color, val = params[i].value; txt += '<div><span class="blue-dot middle" style="background: ' + cl + ';"></span><span>' + sn + ':' + val + units + '</span></div>'; } return txt; } }, legend: { show: true, left: 'right', // icon: "circle", // 修改形狀 itemHeight: 8, // 修改icon圖形大小 itemWidth: 16, // 修改icon圖形大小 itemGap: 8, // 修改間距 textStyle: {color: '#fff', fontSize: 12}// padding: [0, -5, 0, 0], // 修改文字和圖標距離 }, xAxis: { type: "category", data: this.xData, axisTick: {show: true}, axisLine: {show: true, lineStyle: {color: "#4e9bdf"}}, axisLabel: {textStyle: {color: "#365787"}, margin: 10, rotate: 0}, // rotate x軸標識 旋轉角度 boundaryGap: flag, //false:x軸文字貼緊倆邊 }, yAxis: { name: (this.units ? ("單位:" + this.units) : ""), type: "value", max: this.yMax, axisLabel: {textStyle: {color: "#ffffff"}}, //// margin: 10, axisLine: {show: true, lineStyle: {color: "#4e9bdf"}}, splitLine: {lineStyle: {color: "#4e9bdf", type: 'dashed'}}, // dashed-虛線 min: 0, }, series: series }; // console.log(`id -> ${this.id}\noption -> ${JSON.stringify(option)}`); this.myChart.setOption(option); //自適應屏幕 this.updateRsize(this.myChart); }, getSeries() { // 折線圖折線數據 --- series[0].name-折線的名稱 // series[0].data - 折線的數據 var optSeries = []; const seriesData = this.chartData.seriesData; // console.log(`seriesData.length -> ${seriesData.length}\nseriesData -> ${JSON.stringify(seriesData)}`); if (seriesData && seriesData.length > 0) { for (var i = 0, n = seriesData.length; i < n; i++) { // 判斷傳遞過來的 seriesData[i] 中的要展示的echarts圖類型 默認為 bar 類型 柱狀圖 const type = seriesData[i].type || 'bar'; var series = JSON.parse(JSON.stringify(this.seriesBar)); // 克隆對象 this.seriesBar 賦值給 series if ("bar" != type) series = JSON.parse(JSON.stringify(this.seriesLine)); // 克隆對象 this.seriesLine 賦值給 series // 判斷並設置 series.name series.name = seriesData[i].name || series.name; // 判斷並處理傳遞過來的 seriesData[i].data 並設置進 series 中 const tmpSeries = seriesData[i]; if (tmpSeries.data && tmpSeries.data.length > 0) { series.data = tmpSeries.data; // 當數據長度小於 x軸要展示的數據長度時 使用 0 進行補充 if (tmpSeries.data.length < this.xData.length) { for (var j = tmpSeries.data.length, m = this.xData.length; j < m; j++) { series.data.push(0); } } } // 判斷並設置 series.stack 獨立模式 留空不設置 或 堆疊模式 stack:'total' if (seriesData[i].stack) series.stack = seriesData[i].stack; // bar 類型的 if ('bar' == type) { // 判斷並設置柱子寬度 series.barWidth if (seriesData[i].barWidth) series.barWidth = seriesData[i].barWidth; // 判斷並設置 series.itemStyle. if (seriesData[i].itemStyle) { // 判斷並設置 series.itemStyle.barBorderRadius if (seriesData[i].itemStyle.radius) { if (!series.itemStyle) series.itemStyle = {}; series["itemStyle"]["barBorderRadius"] = seriesData[i].itemStyle.radius } // 判斷並設置 series.itemStyle.color const res = this.getItemStyleColor(seriesData[i].itemStyle.color, seriesData[i].itemStyle.colors); if (res) { if (!series.itemStyle) series.itemStyle = {}; series["itemStyle"]["color"] = res; } } } else { // line類型的 // 判斷並設置 series.smooth 圓潤拐點 series.smooth = seriesData[i].smooth || false; if (seriesData[i].color) series.color = seriesData[i].color // 判斷並設置 series.lineStyle if (seriesData[i].lineStyle) { // 判斷並設置 series.lineStyle.width if (seriesData[i].lineStyle.width) { if (!series.lineStyle) series.lineStyle = {}; series["lineStyle"]["width"] = seriesData[i].lineStyle.width; } // 判斷並設置 series.lineStyle.color const res = this.getItemStyleColor(seriesData[i].lineStyle.color, seriesData[i].lineStyle.colors); if (res) { if (!series.lineStyle) series.lineStyle = {}; series["lineStyle"]["color"] = res; } } // 判斷並設置 series.areaStyle if (seriesData[i].areaStyle) { // 判斷並設置 series.areaStyle.color const res = this.getItemStyleColor(seriesData[i].areaStyle.color, seriesData[i].areaStyle.colors); if (res) { if (!series.areaStyle) series.areaStyle = {}; series["areaStyle"]["color"] = res; } } } // 判斷並設置 series.emphasis if (seriesData[i].emphasis) { if (seriesData[i].emphasis.focus) { if (!series.emphasis) series.emphasis = {}; series["emphasis"]["focus"] = seriesData[i].emphasis.focus; } // 判斷並設置 series.emphasis.color const res = this.getItemStyleColor(seriesData[i].emphasis.color, seriesData[i].emphasis.colors); if (res) { if (!series.emphasis) series.emphasis = {}; series["emphasis"]["color"] = res; } } optSeries.push(series); // console.log(`i -> ${i}\nseries -> ${JSON.stringify(series)}\noptSeries -> ${JSON.stringify(optSeries)}`); } } else { // this.seriesBar.data = this.seriesBar.data0; optSeries[0] = this.seriesBar; } // console.log(`optSeries -> ${JSON.stringify(optSeries)}`); return optSeries; }, getItemStyleColor(color, colors) { if (color) { return color; } else if (colors) { const cok = Object.keys(colors); const fx = colors.fx; var cos = []; for (var ii = 0, nn = cok.length; ii < nn; ii++) { if ('fx' != cok[ii] && 0 <= cok[ii] <= 1) cos.push({offset: cok[ii], color: colors[cok[ii]]}); } if (fx && fx.length == 4) { return new echarts.graphic.LinearGradient(fx[0], fx[1], fx[2], fx[3], cos); } else { return new echarts.graphic.LinearGradient(0, 0, 0, 1, cos); } } return undefined; } }, mounted() { // this.initChart(); }, watch: { //動態監聽數據是否變化 chartData: { deep: true, //true為進行深度監聽,false為不進行深度監聽 handler() { this.initChart(); } }, }, }; </script> <style lang="less" scoped></style>
3.2.創建文件 maintenancefundsChart.vue 並引入剛創建的組件, 代碼如下:
<template> <div class="cloud_wrap"> <border-tem-py :width="'100%'"> <!-- 插槽模板 --> <div class="title" slot="title">柱狀折線圖統計</div> <div class="content-box" slot="content"> <div class="layui-row layui-col-space10"> <div class="layui-col-md12"> <bar-line-chart-py :id="'mfChart'" :chartData="chartData" :units="'萬元'" /> </div> </div> </div> </border-tem-py> </div> </template> <script> import barLineChartPy from '../../../../common/barLineChartPY.vue'; // 路徑根據自己實際項目中的進行修改 export default { components: { barLineChartPy }, data() { return { active: 'y', chartData: { xData: [], seriesData: [ { name: '統計', // 必填 data: [123, 330, 236.5, 500, 360.6,188.8,669.0,115,188,55], // 必填 type: 'bar', // 非必填 默認 bar 柱狀圖 // stack: 'total', // 柱狀圖或折線圖展示模式 獨立模式 留空不設置 或 堆疊模式 stack:'total' 非必填 barWidth: 15, // 柱子寬度 非必填 itemStyle: { // 僅柱狀圖生效 非必填 // // radius: 30, // 柱狀圖圓角 數字 或 數字數組 [20, 20, 0, 0] [左上角,右上角,右下角,左下角] // // 柱子顏色 color 單色 colors 漸變色 (color / colors 二選一) // // fx 漸變方向 右/下/左/上四個方位. 而0 0 0 1則代表漸變色從正上方開始 // // 0、1 漸變的位置 以及 相應位置的顏色 取值范圍 0~1 // // color: '', colors: {'fx': [0, 0, 0, 1], /* 漸變的方向 */ 0: '#2D96F3', 1: '#0B40C3'} }, // // 鼠標移動到柱條上時的樣式 // emphasis: { // 柱狀圖 和 折線圖均可 非必填 // focus: 'series', // // color 與 colors 參看 itemStyle 中的說明 // // color: '', // colors: {} // } }, { name: '統計2', // 必填 data: [230, 136, 500, 360, 288, 569, 315, 288, 155], // 必填 type: 'line', // 非必填 默認 bar 柱狀圖 // smooth: true, // 折線圖 轉折點是否圓潤 默認false 非必填 // lineStyle: { // 僅折線圖生效 非必填 // // width: 1, // // color 與 colors 參看 itemStyle 中的說明 // color: '#EB9C06', // // colors: {} // }, // areaStyle: { // 進折線圖生效 折線圖掃過的面積的樣式 非必填 // // color 與 colors 參看 itemStyle 中的說明 // // color: '', // colors: {} // } } ] } }; }, methods:{ btnClick(val) { this.active = val; this.loadData(); }, loadData() { let params = { type: this.active }; this.content = JSON.stringify(params) // 隨機數數組 賦值 生成echarts圖 this.chartData.seriesData[0].data = this.$options.filters['randomNums'](0, 300, 12); this.chartData.seriesData[1].data = this.$options.filters['randomNums'](0, 600, 12); } }, mounted() { this.loadData(); // 定時器 模擬動態加載數據 實時渲染echarts 實現 實時動態echarts const interval = setInterval(() => { this.loadData(); }, 2000); // 通過$once來監聽定時器,在beforeDestroy鈎子可以被清除。 this.$once('hook:beforeDestroy', () => { clearInterval(interval); }); }, }; </script> <style scoped> * { font-family: MicrosoftYaHei; } .cloud_wrap{ z-index: 1; position: relative; cursor: pointer; } .cloud_wrap .layui-col-md12 { min-width: 175px; height: 230px; } </style>
3.3.然后再相關頁面中再引入 maintenancefundsChart.vue 並使用即可;
小貼士:
百度Echarts官網:https://echarts.apache.org/examples/zh/index.html
html中的調色與透明度:https://www.cnblogs.com/jindao3691/p/16093404.html
vue中隨機數、隨機數數組過濾器方法以及在methods中調用:https://www.cnblogs.com/jindao3691/p/16122622.html
vue組件-echarts圓環圖以及legend多列展示 和 legend分頁展示:https://www.cnblogs.com/jindao3691/p/16093592.html
每天進步一點點,點滴記錄,積少成多。
以此做個記錄,
如有不足之處還望多多留言指教!