Echart通用组件基础版本

84 阅读3分钟

能简单支持基础柱状图单系列、多系列、堆叠图、饼图、环形图

主题文件

export const universalTheme = {
    width: 'auto',
    height: 'auto',
    color: [
        '#4e83fd',
        '#50cefb',
        '#935af6',
        '#fad355',
        '#f76964',
        '#ffa53d',
        '#4ea397',
        '#22c3aa',
        '#7bd9a5',
        '#d0648a',
        '#f58db2',
        '#f2b3c9',
        '#82a3f0',
        '#7ed1ef',
        '#a982eb',
    ],
    backgroundColor: 'rgba(255,255,255,0)',
    textStyle: {},
    title: {
        textStyle: {
            color: '#000000'
        },
        subtextStyle: {
            color: '#675e5e'
        }
    },
    line: {
        itemStyle: {
            borderWidth: '2'
        },
        lineStyle: {
            width: '2'
        },
        symbolSize: '8',
        symbol: 'emptyCircle',
        smooth: false
    },
    radar: {
        itemStyle: {
            borderWidth: '2'
        },
        lineStyle: {
            width: '2'
        },
        symbolSize: '8',
        symbol: 'emptyCircle',
        smooth: false
    },
    bar: {
        itemStyle: {
            barBorderWidth: '0',
            barBorderColor: '#eeeeee'
        }
    },
    pie: {
        itemStyle: {
            borderWidth: '0',
            borderColor: '#eeeeee'
        }
    },
    scatter: {
        itemStyle: {
            borderWidth: '0',
            borderColor: '#eeeeee'
        }
    },
    boxplot: {
        itemStyle: {
            borderWidth: '0',
            borderColor: '#eeeeee'
        }
    },
    parallel: {
        itemStyle: {
            borderWidth: '0',
            borderColor: '#eeeeee'
        }
    },
    sankey: {
        itemStyle: {
            borderWidth: '0',
            borderColor: '#eeeeee'
        }
    },
    funnel: {
        itemStyle: {
            borderWidth: '0',
            borderColor: '#eeeeee'
        }
    },
    gauge: {
        itemStyle: {
            borderWidth: '0',
            borderColor: '#eeeeee'
        }
    },
    candlestick: {
        itemStyle: {
            color: '#e44d7d',
            color0: 'transparent',
            borderColor: '#d0648a',
            borderColor0: '#22c3aa',
            borderWidth: '1'
        }
    },
    graph: {
        itemStyle: {
            borderWidth: '0',
            borderColor: '#eeeeee'
        },
        lineStyle: {
            width: '1',
            color: '#4e83fd'
        },
        symbolSize: '8',
        symbol: 'emptyCircle',
        smooth: false,
        color: [
            '#4e83fd',
            '#50cefb',
            '#935af6',
            '#fad355',
            '#f76964',
            '#ffa53d',
            '#4ea397',
            '#22c3aa',
            '#7bd9a5',
            '#d0648a',
            '#f58db2',
            '#f2b3c9',
            '#82a3f0',
            '#7ed1ef',
            '#a982eb',
        ],
        label: {
            color: '#ffffff'
        }
    },
    map: {
        itemStyle: {
            areaColor: '#eeeeee',
            borderColor: '#999999',
            borderWidth: 0.5
        },
        label: {
            color: '#28544e'
        },
        emphasis: {
            itemStyle: {
                areaColor: 'rgba(34,195,170,0.25)',
                borderColor: '#22c3aa',
                borderWidth: 1
            },
            label: {
                color: '#349e8e'
            }
        }
    },
    geo: {
        itemStyle: {
            areaColor: '#eeeeee',
            borderColor: '#999999',
            borderWidth: 0.5
        },
        label: {
            color: '#28544e'
        },
        emphasis: {
            itemStyle: {
                areaColor: 'rgba(34,195,170,0.25)',
                borderColor: '#22c3aa',
                borderWidth: 1
            },
            label: {
                color: '#349e8e'
            }
        }
    },
    categoryAxis: {
        axisLine: {
            show: false,
            lineStyle: {
                // 控制鼠标一到图标上x轴坐标显示的字体颜色
                color: '#cccccc'
            }
        },
        axisTick: {
            show: true,
            lineStyle: {
                // 横坐标轴刻度的颜色
                color: '#eeeeee'
            }
        },
        axisLabel: {
            show: true,
            // 横坐标字体默认的颜色
            color: '#999999'
        },
        splitLine: {
            // 坐标系中的竖线样式控制
            show: false,
            lineStyle: {
                color: [
                    '#eeeeee'
                ]
            }
        },
        splitArea: {
            // 坐标系被竖线分割为几份后,每份区间的背景色等控制
            show: false,
            areaStyle: {
                color: [
                    'rgba(250,250,250,0.05)',
                    'rgba(200,200,200,0.02)'
                ]
            }
        }
    },
    valueAxis: {
        axisLine: {
            // y轴样式控制
            show: true,
            lineStyle: {
                color: '#eeeeee'
            }
        },
        axisTick: {
            // y轴刻度线样式控制
            show: false,
            lineStyle: {
                color: '#333'
            }
        },
        axisLabel: {
            // y轴字体样式控制
            show: true,
            color: '#999999'
        },
        splitLine: {
            // 坐标系中的横线样式控制
            show: true,
            lineStyle: {
                color: [
                    '#eeeeee'
                ]
            }
        },
        splitArea: {
            show: false,
            areaStyle: {
                color: [
                    'rgba(250,250,250,0.05)',
                    'rgba(200,200,200,0.02)'
                ]
            }
        }
    },
    logAxis: {
        axisLine: {
            show: true,
            lineStyle: {
                color: '#eeeeee'
            }
        },
        axisTick: {
            show: false,
            lineStyle: {
                color: '#333'
            }
        },
        axisLabel: {
            show: true,
            color: '#999999'
        },
        splitLine: {
            show: true,
            lineStyle: {
                color: [
                    '#eeeeee'
                ]
            }
        },
        splitArea: {
            show: false,
            areaStyle: {
                color: [
                    'rgba(250,250,250,0.05)',
                    'rgba(200,200,200,0.02)'
                ]
            }
        }
    },
    timeAxis: {
        axisLine: {
            show: true,
            lineStyle: {
                color: '#eeeeee'
            }
        },
        axisTick: {
            show: false,
            lineStyle: {
                color: '#333'
            }
        },
        axisLabel: {
            show: true,
            color: '#999999'
        },
        splitLine: {
            show: true,
            lineStyle: {
                color: [
                    '#eeeeee'
                ]
            }
        },
        splitArea: {
            show: false,
            areaStyle: {
                color: [
                    'rgba(250,250,250,0.05)',
                    'rgba(200,200,200,0.02)'
                ]
            }
        }
    },
    toolbox: {
        iconStyle: {
            borderColor: '#999999'
        },
        emphasis: {
            iconStyle: {
                borderColor: '#666666'
            }
        }
    },
    legend: {
        textStyle: {
            color: '#999999'
        }
    },
    tooltip: {
        axisPointer: {
            lineStyle: {
                color: '#cccccc',
                width: 1
            },
            crossStyle: {
                color: '#cccccc',
                width: 1
            }
        }
    },
    timeline: {
        lineStyle: {
            color: '#4e83fd',
            width: 1
        },
        itemStyle: {
            color: '#4e83fd',
            borderWidth: 1
        },
        controlStyle: {
            color: '#4e83fd',
            borderColor: '#4e83fd',
            borderWidth: 0.5
        },
        checkpointStyle: {
            color: '#4e83fd',
            borderColor: '#f5f5f5'
        },
        label: {
            color: '#4e83fd'
        },
        emphasis: {
            itemStyle: {
                color: '#4e83fd'
            },
            controlStyle: {
                color: '#4e83fd',
                borderColor: '#4e83fd',
                borderWidth: 0.5
            },
            label: {
                color: '#4e83fd'
            }
        }
    },
    visualMap: {
        color: [
            '#d0648a',
            '#22c3aa',
            '#adfff1'
        ]
    },
    dataZoom: {
        backgroundColor: 'rgba(255,255,255,0)',
        dataBackgroundColor: 'rgba(222,222,222,1)',
        fillerColor: 'rgba(114,230,212,0.25)',
        handleColor: '#cccccc',
        handleSize: '100%',
        textStyle: {
            color: '#999999'
        }
    },
    markPoint: {
        label: {
            color: '#ffffff'
        },
        emphasis: {
            label: {
                color: '#ffffff'
            }
        }
    }
}

通用组件

<!-- 图表容器 -->
<template>
  <div
    class="chart-container"
    ref="charts"
    :style="{
      width: chartParentWidth
    }"
  ></div>
</template>
<script>
import * as echarts from 'echarts'
import { universalTheme } from './universal.js'
// console.log('universalThemeuniversalTheme', universalTheme)
export default {
  name: 'universalChartComponent',
  props: {
    // 图表的宽度
    chartParentWidth: {
      type: String,
      default: '100%'
    },
    // 标题
    title: {
      type: String,
      default: ''
    },
    // 图表类型
    seriesType: {
      type: String,
      default: ''
    },
    //数据集
    dimensions: {
      type: Array,
      default: () => {
        return []
      }
    },
    source: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 是否为推叠图
    isStack: {
      type: Boolean,
      default: false
    },
    // 是否为环形图
    isAnnular: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    // 是否为多系列
    isMultiSeries() {
      if (this.dimensions > 2) {
        return true
      } else {
        return false
      }
    }
  },
  data() {
    return {
      charts: echarts,
      myCharts: null, // 当前图表实例
      baseOption: {
        dataset: [
          {
            // dimensions: this.dimensions,
            source: [this.dimensions, ...this.source]
          }
        ],
        // 基础配置
        legend: {
          type: 'scroll',
          width: '70%',
          align: 'right',
          itemWidth: 15,
          itemHeight: 15,
          itemGap: 11
        },
        grid: {
          // 包含文本
          // left:'left',
          containLabel: true
        },

        toolbox: {
          show: true,
          right: '30px',
          feature: {
            dataView: {
              // show:this.dataViewShow||false,
              show: false,
              readOnly: false,
              title: '列表视图',
              width: '110%',
              lang: [
                '<div style="padding: 0 10px;margin-top:-18px;margin-left:-28px;background:#fff;">数据列表</div>',
                `<div style="
                  position: absolute;
                  top: -25px;
                  background: #1890ff;
                  right: 22px;
                  width: 59px;
                  height: 30px;
                  display: flex;
                  justify-content: center;
                  align-items: center;
                  border-radius: 4px;
                  font-size: 12px;
                  z-index: 99999999;
                  letter-spacing: 4px;
              ">关闭</div>`,
                '<div style="background:#fff;position: absolute;top: 0;right: 0;z-index: 333;width: 30px;" @click="javascrupt:;">刷新</div>'
              ],
              buttonColor: '#1890ff',
              buttonTextColor: '#fff',
              optionToContent: opt => {
                var axisData = opt.xAxis[0].data || opt.yAxis[0].data //x轴作为条件,y轴需改成yAxis[0].data;
                var series = opt.series
                var tdHeads = '<th  style="padding:0 10px;height:30px;background-color: #eeeeee;">名称</th>'
                series.forEach(function(item) {
                  tdHeads += '<th style="padding: 0 10px;height:30px;background-color: #eeeeee;">' + item.name + '</th>'
                })
                var table =
                  '<table class="data-view-table" border="1" style="height:100%;width:100%;border-collapse:collapse;font-size:14px;text-align:center"><thead><tr>' +
                  tdHeads +
                  '</tr></thead><tbody>'
                var tdBodys = ''
                for (var i = 0, l = axisData.length; i < l; i++) {
                  for (var j = 0; j < series.length; j++) {
                    if (typeof series[j].data[i] == 'object') {
                      tdBodys += '<td>' + series[j].data[i].value + '</td>'
                    } else {
                      tdBodys += '<td>' + series[j].data[i] + '</td>'
                    }
                  }
                  table +=
                    '<tr style="height: 30px;"><td style="padding: 0 10px">' + axisData[i] + '</td>' + tdBodys + '</tr>'
                  tdBodys = ''
                }
                table += '</tbody></table>'
                return table
              }
            },
            magicType: (() => {
              if (this.seriesType !== 'pie') {
                return {
                  type: ['line', 'bar'],
                  title: {
                    line: '折线图切换',
                    bar: '柱形图切换'
                  }
                }
              } else {
                return {}
              }
            })()
          }
        },
        dataZoom: []
      },
      barLine: {
        series: (() => {
          // [{ type: this.seriesType }]
          let dimensions = [...this.dimensions]
          let colName = dimensions.shift()
          let result = []
          let stack = ''
          if (this.isStack) {
            stack = 'total'
          }
          dimensions.map((element, index) => {
            result.push({
              type: this.seriesType,
              stack: stack || element,
              barMaxWidth: 30, // 柱子宽度smooth: true,
              showAllSymbol: true, //显示所有图形。
              // symbol: 'circle', //标记的图形为实心圆
              symbolSize: 8, //标记的大小
              universalTransition: true,
              animationDurationUpdate: 1000,
              label: {
                show: true
                // position: 'inside',
              }
            })
          })
          return result
        })(),
        // / 声明一个 X 轴,类目轴(category)。默认情况下,类目轴对应到 dataset 第一列。
        xAxis: { type: 'category' },
        // 声明一个 Y 轴,数值轴。
        yAxis: {},
        tooltip: {
          trigger: 'axis',
          backgroundColor: 'rgba(1, 13, 19, 0.5)',
          order: 'valueDesc',
          axisPointer: {
            type: this.packetPolymerization ? 'shadow' : 'cross',
            crossStyle: {
              color: '#666',
              type: 'dashed'
            }
          },
          formatter: datas => {
            let outHtml = `<div style="
              display: flex;
              flex-wrap: wrap;
              max-width:${datas.length > 20 ? ' 900px' : '150px'};
              max-height: 400px;
              overflow: hidden;
          "><div style="width:100%;">${datas[0].name || ''}</div>`
            datas.map((element, index) => {
              let dataItem = [...element.value]
              dataItem.shift()
              // console.log('dataItem--------', dataItem)
              let divStr = `<div class="formatter" style="display:inline-block;margin-right:10px;">
                <div>
                    ${element.marker} <span class="label">${element.seriesName}:</span>
                    <span class="cont">${dataItem[index]}</span>
                    </div>
                </div>`
              outHtml += divStr
            })
            outHtml += '</div>'
            return outHtml
          }
        }
      },
      pie: {
        tooltip: {
          trigger: 'item'
        },
        legend: (() => {
          return {
            type: 'scroll',
            orient: 'vertical',
            height: '80%',
            right: '27px',
            top: 'center',
            itemWidth: 15,
            itemHeight: 15,
            itemGap: 11,
            formatter: name => {
              let total = 0
              this.source.map(element => {
                total += element[1]
              })
              for (var i = 0; i < this.source.length; i++) {
                if (name == this.source[i][0]) {
                  let persent = 0
                  if (total != 0) {
                    persent = ((this.source[i][1] / total) * 100).toFixed(2)
                  }
                  return `${name}:${this.dimensions[1]}为${this.source[i][1]}, 占比为${persent}%`
                }
              }
            }
          }
        })(),
        series: (() => {
          return [
            {
              type: 'pie',
              radius: (() => {
                if (this.isAnnular) {
                  return ['25%', '45%']
                } else {
                  return '50%'
                }
              })(),
              center: ['30%', '50%'],
              label: {
                fontSize: 12
              }
            }
          ]
        })()
      }
    }
  },
  mounted() {
    this.$refs['charts'].innerHTML = ''
    // 注册并使用主题
    this.charts.registerTheme('universalTheme', universalTheme)
    this.myCharts = this.charts.init(this.$refs['charts'], 'universalTheme')
    this.$nextTick(() => {
      this.init()
    })
    window.addEventListener('resize', () => {
      this.myCharts && this.myCharts.resize()
    })
  },
  methods: {
    showLoading(text = '加载中,请稍候...') {
      this.myCharts.showLoading({ text, color: '#1890ff', textColor: '#1890ff' })
    },
    hideLoading() {
      this.myCharts.hideLoading()
    },
    init() {
      this.showLoading()
      setTimeout(() => {
        let option = {}
        if (this.seriesType == 'bar' || this.seriesType == 'line') {
          option = Object.assign(this.baseOption, this['barLine'])
        }
        if (this.seriesType == 'pie') {
          option = Object.assign(this.baseOption, this['pie'])
        }
        this.myCharts.setOption(option, true)
        console.log('universal---------', option, this.myCharts)
        this.myCharts && this.myCharts.resize()
        this.hideLoading()
        this.myCharts.on('click', params => {
          this.$emit('onClickHandle', params)
        })
      }, 10)
    }
  }
}
</script>
<style lang="scss" scoped>
.chart-container {
  height: 700px;
}
</style>

组件使用

      <universal-chart
        v-if="index == 1 && !loading"
        key="diy_x1"
        title="多系列折线图"
        seriesType="line"
        :dimensions="item.dimensions"
        :source="item.source"
      ></universal-chart>
      <universal-chart
        v-if="index == 1 && !loading"
        key="diy_x"
        title="多系列柱状图"
        seriesType="bar"
        :dimensions="item.dimensions"
        :source="item.source"
      ></universal-chart>
      <universal-chart
        v-if="index == 1 && !loading"
        key="diy_x2"
        title="堆叠柱状图"
        seriesType="bar"
        :isStack="true"
        :dimensions="item.dimensions"
        :source="item.source"
      ></universal-chart>
      <universal-chart
        v-if="index == 3 && !loading"
        key="diy_x0"
        title="基础柱状图"
        seriesType="bar"
        :dimensions="item.dimensions"
        :source="item.source"
      ></universal-chart>
      <!-- 饼图 -->
      <universal-chart
        v-if="index == 3 && !loading"
        key="diy_x0"
        title="基础饼图"
        seriesType="pie"
        :dimensions="item.dimensions"
        :source="item.source"
      ></universal-chart>
      <!-- 饼图 -->
      <universal-chart
        v-if="index == 3 && !loading"
        key="diy_x02"
        title="基础环形图"
        seriesType="pie"
        :isAnnular="true"
        :dimensions="item.dimensions"
        :source="item.source"
      ></universal-chart>

效果图

image.png

image.png

image.png

image.png

image.png

image.png