“我正在参加「掘金·启航计划」”
前言
近期发现很多项目中都会用到折线图,于是搜集了一些资料,整理出了一份简洁、灵活的折线图,话不多说,直接上代码:
// 封装的折线图组件 vue2.0版本
<template>
<div :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import * as echarts from 'echarts/lib/echarts'
import 'echarts/lib/component/tooltip'
import 'echarts/lib/component/legend'
import resize from './resize'
export default {
name: 'LineChart',
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
},
yAxisName: {
type: String,
default: ''
},
width: {
type: String,
default: '100%'
},
autoResize: {
type: Boolean,
default: true
},
chartData: {
type: Object,
default: () => {}
}
},
data() {
return {
chart: null,
height: '336px'
}
},
watch: {
chartData: {
deep: true,
handler(val) {
this.$nextTick(() => {
this.setOptions(val)
})
}
}
},
mounted() {
this.$nextTick(() => {
this.initChart(this.chartData)
})
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart(chartData) {
this.chart = echarts.init(this.$el, 'macarons')
this.setOptions(chartData)
},
// 计算最大值
calMax(arr) {
let max = 0
arr.forEach((el) => {
el.forEach((el1) => {
if (!(el1 === undefined || el1 === '')) {
if (max < el1) {
max = el1
}
}
})
})
const maxint = Math.ceil(max / 950) // 不让最高的值超过最上面的刻度
const maxval = maxint * 1000 // 让显示的刻度是整数
return maxval
},
setOptions({ xData, legendData, yData } = {}) {
let series = []
let legends = []
let arr = []
let max1 = ''
let max2 = ''
let max3 = ''
let Min = 0
let Max = ''
let splitNumber = 5
for (var i in legendData) {
if (i === '0') {
legends.push({
name: legendData[i],
yData: yData[i],
color: 'rgba(12,137,114)',
areaColor: ['rgba(12,137,114, .1)', 'rgba(12,137,114, .02)']
})
yData[i].forEach(j => {
j < 0 && (Min = -1, splitNumber = 2)
arr.push(Math.abs(j))
})
max1 = this.calMax([arr])
} else if (i === '1') {
legends.push({
name: legendData[i],
yData: yData[i],
color: '#E48A2A',
areaColor: ['rgba(228, 138, 44, .1)', 'rgba(228, 138, 44, .02)']
})
yData[i].forEach(j => {
j < 0 && (Min = -1, splitNumber = 2)
arr.push(Math.abs(j))
})
max2 = this.calMax([arr])
} else if (i === '2') {
legends.push({
name: legendData[i],
yData: yData[i],
color: '#2CC3E4',
areaColor: ['rgba(44, 195, 228, .1)', 'rgba(44, 195, 228, .02)']
})
yData[i].forEach(j => {
j < 0 && (Min = -1, splitNumber = 2)
arr.push(Math.abs(j))
})
max3 = this.calMax([arr])
}
}
Max = (max1 > max2 > max3) ? max1 : (max2 > max3 ? max2 : max3)
legends.forEach(i => {
series.push({
name: i.name,
type: 'line',
smooth: true,
// showSymbol: false,
symbol: 'emptyCircle',
symbolSize: 6,
data: i.yData,
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 0.5, [{
offset: 0,
color: i.areaColor[0]
}, {
offset: 1,
color: i.areaColor[1]
}], false)
}
},
itemStyle: {
color: '#6c50f3',
normal: {
color: i.color
}
},
lineStyle: {
normal: {
width: 2
}
}
})
})
this.chart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
lineStyle: {
color: '#ddd'
}
},
backgroundColor: 'rgba(255,255,255,1)',
padding: [5, 10],
textStyle: {
color: '#7588E4'
},
extraCssText: 'box-shadow: 0 0 5px rgba(0,0,0,0.3)'
},
legend: {
top: '30px',
right: 'center',
itemWidth: 10,
itemHeight: 10,
orient: 'horizontal',
data: legendData,
icon: 'roundRect' // 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow'
},
grid: {
top: '80px',
left: '3%',
right: '5%',
bottom: '8%',
containLabel: true
},
xAxis: {
type: 'category',
data: xData,
boundaryGap: false,
splitLine: {
show: true,
interval: 'auto',
lineStyle: {
color: ['#fff']
}
},
axisTick: {
// show: false
},
axisLine: {
lineStyle: {
color: '#999',
fontSize: 12
}
},
axisLabel: {
margin: 10,
textStyle: {
fontSize: 12
}
}
},
yAxis: {
name: this.yAxisName,
nameTextStyle: {
padding: [0, 10, 5, 0]
},
type: 'value',
max: Max,
min: Min === 0 ? Min : -Max,
splitNumber: splitNumber,
interval: Max / splitNumber,
splitLine: {
lineStyle: {
color: ['#EDEDF2']
}
},
axisTick: {
// show: false
},
axisLine: {
lineStyle: {
color: '#999',
fontSize: 14
}
},
axisLabel: {
margin: 10,
textStyle: {
fontSize: 14
}
}
},
series: series
})
}
}
}
</script>
// 父组件引用
<LineCharts :chart-data="lineChartData" :y-axis-name="yAxisName" />
data() {
return {
yAxisName: '单位:元',
lineChartData: {
xData: [],
legendData: ['去年同期', '盈亏额'], // 根据数组的长度渲染出对应的指标数
yData: [[11, 11], [22, 22]]
}
}
}
最终呈现效果: