前言:項目需要,需要畫一段數據的折線圖,折線圖根據正常數據和異常數據顯示兩種顏色的線,並且在鼠標經過異常線橫坐標時,標記該點往后的十個點組成的線,標記可以有很多方式: 1,第一個點和最后一個點做標記markPoint,2,第一個點到第十個點做區域陰影markArea,3,第一個點和第十個點都變顏色......等,反應這一段線就可以,我這里是選擇的第二種方式,
效果圖:
代碼如下: Echarts.vue文件(寫了一個echarts的組件)
html部分
<template> <div :id="id"></div> </template>
js部分
<script> import echarts from 'echarts' import chinaJSON from '@/assets/data/chinaMap.json' echarts.registerMap('china', chinaJSON) export default { data () { return { chart: null, n: 0 } }, props: ['id', 'option'], mounted () { let vm = this this.chart = echarts.init(document.getElementById(this.id)) let baseOption = { } let options = Object.assign({}, baseOption, this.option) this.chart.setOption(options, { notMerge:true, }) // 以下為echarts的各種方法,我這里只使用了datazoom, 和updateAxisPointer方法。 // this.chart.on('click', function (params) { // vm.$emit('click-chart', params) // }) // this.chart.on('mouseover', function(params) { // vm.$emit('mouseoverChart', params) // }) // this.chart.on('mouseout', function(params) { // vm.$emit('mouseoutChart', params) // }) this.chart.on('datazoom', function (params) { vm.$emit('datazoomChart', params) }) this.chart.on('updateAxisPointer', function(params) { vm.$emit('updateAxisPointer', params) }) }, watch: { option: { handler(newVal, oldVal) { if (this.chart) { if (newVal) { this.chart.setOption(newVal); } else { this.chart.setOption(oldVal); } } else { this.init(); } }, deep: true //對象內部屬性的監聽,關鍵。 } } // beforeDestroy(){ // this.chart.dispose() // } } </script>
配置chartsOPtions.js
export function lineOption(xData, yData, xname, yname, pieces, trendList) const option = { tooltip: { trigger: "axis", formatter: (params) => { let result = params[0].marker + params[0].name +'</br>' for(let n in trendList){ if(n == params[0].name){ result += `<ul>` if(trendList[n].fault){ result += ` <li> <span>斜率:</span><span></span>${trendList[n].fault.ratio}</span> </li> <li> <span>最低差值百分比:</span><span></span>${trendList[n].fault.min_percent}</span> </li> <li> <span>開始時間:</span><span></span>${trendList[n].fault.start_time}</span> </li> <li> <span>結束時間:</span><span></span>${trendList[n].fault.end_time}</span> </li> <li> <span>窗口內開始差值百分比:</span><span></span>${trendList[n].fault.start_percent}</span> </li> <li> <span>窗口內結束差值百分比:</span><span></span>${trendList[n].fault.end_percent}</span> </li> ` } result +=` <li> <span>趨勢差值百分比:</span><span></span>${trendList[n].trend.percent}</span> </li> <li> <span>趨勢窗口開始時間:</span><span></span>${trendList[n].trend.start_time}</span> </li> <li> <span>趨勢窗口結束時間:</span><span></span>${trendList[n].trend.end_time}</span> </li> </ul> ` } } return result; } }, dataZoom: [ { type: "inside", start: 0, end: 100, xAxisIndex: [0] }, { start: 0, end: 100, } ], grid: { left: "2%", right: "5%", top: "10%", containLabel: true }, xAxis: [ { type: 'category', boundaryGap: false, name: xname, data: xData, axisTick: { alignWithLabel: true }, axisLine: { lineStyle: { color: "#999" } } } ], yAxis: [ { type: "value", name: yname, splitNumber: 7, // scale: true, splitLine: { lineStyle: { type: "dashed", color: "#DDD" } }, axisLine: { show: false, lineStyle: { color: "#999" } }, axisTick: { show: false, // axisTick: { // alignWithLabel: true // }, }, nameTextStyle: { color: "#555" }, splitArea: { show: false } }, ], visualMap: { show: false, dimension: 0, pieces: pieces, outOfRange: { color: 'grey' }, seriesIndex: 0 }, series: [{ data: yData, // markPoint: {}, type: "line", symbol:'circle', sampling: 'lttb', markLine: { silent: true, lineStyle: { color: '#333' }, data: [{ yAxis: 2 }] }, }, { data: yData2, type: "line", symbol:'none', showSymbol: false,//這兩個屬性可以讓折線圖只在鼠標進入的時候在該數據畫點,而不每個數據都畫點,因為每個數據都畫點在數據量大的時候會非常卡。 sampling: 'lttb' } ], } return option }
調用文件xxx.js
html文件
<div @mouseleave="mouseleaveChart">
<!-- @mouseoverChart="mouseoverChart" -->
<echart v-if="trendList && trendList.length > 0" id="failureTimesOption" @datazoomChart="datazoomChart" :option="failureTimesOption" @updateAxisPointer="updateAxisPointer" class="failure-time-chart"></echart>
</div>
js部分
里面注釋有詳細解釋各個方法
import Echart from "./components/Echart"; export default { mixins: [tracker], data(){ return { failureTimesOption: {}, yData: [], xname: '', yname: '', pieces: [], xData: [], dataZoom: {}, // trendList: [ // {trend: {start_time: "2019-08-19 13:14:40", end_time: "2019-10-21 00:10:31", percent: 0}, sign: "0"} // {trend: {start_time: "2019-08-19 13:14:40", end_time: "2019-10-21 00:10:31", percent: 0}, sign: "0"} // {trend: {start_time: "2019-08-19 13:31:20", end_time: "2019-10-21 17:27:23", percent: 0.01}, sign: "0"} // {trend: {start_time: "2019-08-19 13:31:20", end_time: "2019-10-21 17:27:23", percent: 0.01}, sign: "1"} // {trend: {start_time: "2019-08-29 19:06:58", end_time: "2019-10-21 17:44:03", percent: 0.01}, sign: "1"} // {trend: {start_time: "2019-08-29 19:06:58", end_time: "2019-10-21 17:44:03", percent: 0.01}, sign: "1"} // {trend: {start_time: "2019-09-01 18:36:21", end_time: "2019-10-23 12:15:49", percent: 0.01}, sign: "0"} // {trend: {start_time: "2019-09-01 18:36:21", end_time: "2019-10-23 12:15:49", percent: 0.01}, sign: "0"} // {trend: {start_time: "2019-09-01 18:53:01", end_time: "2019-10-23 12:32:29", percent: 0.01}, sign: "0"} // ] // 后端給的數據格式是這樣的 } }, components: { Echart }, methods: { // 從后端拿到數據后初始化線 getEchart(trendList){ // trendList是后端給的數據,格式在data里面舉了例子,線的顏色主要是用sign來區分,singn為0組成的點連程的線為green,為1則是紅色 this.yData = [] // 縱坐標數據 this.xname = '時間批序號' //橫坐標名字 this.yname = '差值百分比'// 縱坐標名字 this.pieces = [] //線改變顏色的配置 this.xData = [] // x軸數據 let flag = 0 // 線改變顏色的關鍵標記 for(let n in trendList){ let obj = {} obj.value = Number(n) obj.sign = Number(trendList[n].sign) this.xData.push(Number(n)) //x軸數據 this.yData.push(trendList[n].trend.percent) // y軸數據 // 設置線的顏色 if( Number(n) + 1 < trendList.length){ if(trendList[Number(n)].sign != trendList[Number(n) + 1].sign){ if(trendList[Number(n)].sign == '0'){ this.pieces.push({ color: 'green', gte: flag, lt: Number(n) + 1 }) flag = Number(n) + 1 }else { this.pieces.push({ color: 'red', gte: flag, lt: Number(n) + 1, }) flag = Number(n) + 1 } } } } // 設置最后區域線顏色 if(trendList[trendList.length - 1].sign == '0'){ this.pieces.push({ color: 'green', gte: flag, lt: trendList.length - 1, }) }else { this.pieces.push({ color: 'red', gte: flag, lt: trendList.length - 1, }) } console.log("this.pieces", this.pieces) this.trendList = trendList // 把處理好的線顏色的配置賦值給echarts this.$nextTick(() => { this.failureTimesOption = lineOption(this.xData, this.yData, this.xname, this.yname, this.pieces, this.trendList) }) }, // 鼠標經過橫坐標時觸發方法,我之前用的是mouseover的方法,但是我發現如果數據特別多,那點就非常密集,很難選中點,難以觸發想要的線段標記方法,所以改為觸發該點橫坐標就執行標記線段方法 updateAxisPointer(params){ // 數據比較大的時候,坐標軸縮放,由於鼠標觸發線段標記方法時會重置option(watch方法里面有寫),所以雖然縮放了但是鼠標一旦移動想去看看縮放后其他點的標記情況那折線圖就被重置了,縮放就回到最初了,所以這里需要保留縮放后的dataZoom,這樣在觸發橫坐標方法的時候依舊賦值縮放過的dataZoom,這樣dataZoom就不會每次都被初始化了 if (this.failureTimesOption.dataZoom && this.dataZoom) { this.failureTimesOption.dataZoom[0].start = this.dataZoom.start; this.failureTimesOption.dataZoom[0].end = this.dataZoom.end; } //獲取標記區域所需的數據,即獲取echarts的一個配置項markArea,所需內容 let markArea = {} if(params.axesInfo && params.axesInfo.length > 0){ let dataIndex = params.dataIndex let dataIndex10 = params.dataIndex + 9 // 這里是標記規則,我們項目的規則是,1,綠色線的點不觸發標記方法,2,綠色點的最后十個點是不觸發的, if(this.trendList[dataIndex].fault){ if(this.trendList[dataIndex] && this.trendList[dataIndex].sign == 1 && this.trendList[dataIndex10] && this.trendList[dataIndex10].sign != 0){ for(let n in this.trendList){ if(n == dataIndex10){ markArea = {
itemStyle: {
color: 'rgba(255, 173, 177, 0.2)'
},
data: [[ {xAxis: dataIndex}, {xAxis: dataIndex10} ]] } this.$set(this.failureTimesOption.series[0], 'markArea', markArea) } } } }else { let markArea = {data: []} this.$set(this.failureTimesOption.series[0], 'markArea', markArea) } } }, // 當鼠標離開echarts元素塊時,標記消失的 mouseleaveChart(){ let markArea = {data: []} this.$set(this.failureTimesOption.series[0], 'markArea', markArea) }, // 縮放方法,獲取縮放后的dataZoom datazoomChart(event){ // console.log("datazoomChart", event) if (event.batch) { // 在圖表內使用鼠標滾輪縮放 this.dataZoom = { start: event.batch[0].start, end: event.batch[0].end } } else { // 使用滑塊縮放 this.dataZoom = { start: event.start, end: event.end } } } } }