vue项目封装的echart中bar柱状图组件,自用效果不错

862 阅读1分钟

最近项目开发需求时,需要用到echart中的bar柱状图,本来想封装一个完整可复用的ehcart组件,后面发现options中内容基本不可能都适用,最后自己封装了一个较为好用的组件共享

// legend图例放在template中因为更好定位,样式也更加多变化
<template>
  <div class="bus-group-chart">
    <div
      ref="chart"
      class="chart"
    />

    <p
      v-if="sum"
      class="sum"
    >
      累计:
      <strong>{{ sum }}</strong>
      {{ unit }}
    </p>

    <div class="legend-list">
      <div
        v-for="(item, index) in data"
        :key="index"
        class="legend-item"
      >
        <div v-if="item.name">
          <i
            class="color"
            :style="{background: colorList[index]}"
          />
          <span>{{ item.name }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
/**
 * 普通面板
 *
 * @prop {Array} [data] echart上的渲染数据
 * @prop {Number} [sum] 页面上的累计值
 * @prop {String} [unit] 数值单位
 * @prop {Boolean} [xyExchange] 交互xy轴位置
 * @prop {String, Number} [barWidth] 柱形宽度,可用数字和百分比
 * @prop {Boolean} [sameColor] 同一种类柱形颜色是否为同色
 *
 */
import * as echarts from "@/components/chart/echarts";

// COLOR_LIST是作为柱形图颜色库,取色按照顺序依次使用
const COLOR_LIST = ["#0091FF", "#0AC79D", "#9BE74C", "#F99151"]

export default {
  props: {
    data: {
      type: Array,
      default () {
        return []
      }
    },
    sum: {
      type: Number,
      default: 0
    },
    unit: {
      type: String,
      default: ""
    },
    xyExchange: {
      type: Boolean,
      default: false
    },
    // barWidth柱状宽度,可以为数字也可以是百分比
    barWidth: {
      type: [Number, String],
      default () {
        return ""
      }
    },
    sameColor: {
      type: Boolean,
      default: true
    }
  },
  data () {
    return {
      colorList: COLOR_LIST
    }
  },
  watch: {
    data () {
      this.update()
    }
  },
  mounted () {
    this.initChart()
    this.update()
  },
  beforeDestroy () {
    this.chart && this.chart.dispose()
  },
  methods: {
    // 声明chart变量
    initChart () {
      this.chart = echarts.init(this.$refs.chart)
    },
    // 每次data值改变都会触发update函数,让echart视图更新
    update () {
      if (!this.data.length) {
        return
      }

      const categoryList = this.data[0].data.map((item) => {
        return item.name
      })
      // 默认为y轴
      const valAxis = [
        {
          type: "value",
          // axisLine: 坐标轴轴线设置
          axisLine: { show: false },
          // axisLine: 坐标轴刻度线设置
          axisTick: { show: false },
          // axisLine: 坐标轴刻度标签设置
          axisLabel: {
            align: "right",
            fontSize: 10
          },
          // splitLine: 坐标轴在 [grid](直角坐标系内绘图网格) 区域中的分隔线
          splitLine: {
            lineStyle: {
              opacity: 0.1
            }
          }
        }
      ]
      // 默认为x轴
      const cateAxis = {
        type: "category",
        axisTick: { show: false },
        axisLine: {
          lineStyle: {
            width: 1,
            opacity: 0.5
          }
        },
        axisLabel: {
          // 坐标轴刻度标签的显示间隔,0为强制显示所有标签,1为隔一个显示一个标签
          interval: 0,
        },
        data: categoryList,
      };
      const series = this.data.map((category, index) => {
        const { name, data } = category
        // valueList: 柱形图的data来源
        const valueList = data.map((item) => {
          return item.value
        })
        // color: 每条柱形使用的颜色,如果this.sameColor使用同色,则从颜色库中获取单一颜色,否则获取多样颜色,params为多条柱形数据
        const color = (params) => {
          if (this.sameColor) {
            return this.colorList[index]
          } else {
            return this.colorList[params.dataIndex]
          }
        }
        const series = {
          name: name,
          type: "bar",
          // barWidth: 如果外部不传barWidth则显示默认值
          barWidth: this.barWidth || "",
          // barGap: 不同系列的柱间距离
          barGap: 0,
          labelOption: {
            show: true,
          },
          // itemStyle:柱形图样式
          itemStyle: {
            color
          },
          data: valueList,
        }
        return series
      })
      const option = {
        textStyle: {
          color: "#fff"
        },
        // tooltip:提示框组件
        tooltip: {
          // trigger触发类型:'item'数据项图形触发,'axis'坐标轴触发
          trigger: "axis",
          backgroundColor: "rgba(31,76,117,0.9)",
          borderColor: "#1F9CB4",
          padding: [8, 12],
          textStyle: {
            color: "#FFF",
            fontSize: 14
          },
          // axisPointer: 坐标轴指示器配置项,shadow为选中显示阴影
          axisPointer: {
            type: "shadow"
          },
          // formatter: 提示框浮层内容格式器,支持字符串模板和回调函数两种形式。
          formatter: (params) => {
            let toolTip = `${params[0].name}${params.length > 1 ? "<br>" : ""}`;
            params.forEach((item, index) => {
              toolTip += `${item.seriesName}${item.value}${this.unit}<br>`
            })
            return toolTip
          }
        },
        // grid: 直角坐标系内绘图网格
        grid: {
          top: 58,
          bottom: 0,
          left: 0,
          right: 5,
          containLabel: true,
          borderWidth: 0,
        },
        // this.xyExchange: 更换xy轴位置
        xAxis: this.xyExchange ? valAxis : cateAxis,
        yAxis: this.xyExchange ? cateAxis : valAxis,
        series: series,
      }
      this.chart.setOption(option)
    }
  }
}
</script>

<style lang="scss">
.bus-group-chart {
  position: relative;
  height: 100%;

  .chart {
    height: 100%;
  }

  .sum {
    position: absolute;
    top: -40px;
    right: 10px;
    font-size: 13px;
    color: #FFF;
  }

  .legend-list {
    position: absolute;
    left: 0;
    width: 100%;
    bottom: -40px;
    display: flex;
    justify-content: flex-end;
    font-size: $font-size-small;
    .legend-item {
      margin-right: 16px;
      .color {
        display: inline-block;
        width: 10px;
        height: 10px;
        vertical-align: baseline;
        margin-right: 8px;
      }
    }
  }
}
</style>

组件使用:
    <bar-group-chart
      :data="inforChartData"
      unit="s"
      bar-width="30"
      :same-color="false"
    />
    inforChartData: [
        data: [
          [name: "驻站", value: 1000],
          [name: "车速", value: 1500],
          [name: "信号", value: 2500],
          [name: "交通", value: 4500]
        ],
        name: ""
    ]

QQ截图20220223213120.png