简洁、灵活的echarts折线图

378 阅读1分钟

“我正在参加「掘金·启航计划」”

前言
近期发现很多项目中都会用到折线图,于是搜集了一些资料,整理出了一份简洁、灵活的折线图,话不多说,直接上代码:
// 封装的折线图组件 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]]
        }
    }
}

最终呈现效果: