vue之echart图表的封装

发布时间 2023-10-23 20:36:06作者: 深巷漫步

1、构建echart公用组件

  

<template>
  <div :class="className" :style="{ width, height }"></div>
</template>

<script>
import echarts from "echarts";
require("echarts/theme/macarons"); // echarts theme
import resize from "./mixins/resize";

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: "chart",
    },
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "300px",
    },
    chartOption: {
      type: Object,
      default: () => {},
    },
  },
  data() {
    return {
      chart: null,
    };
  },
  watch: {
    chartOption: {
      deep: true,
      handler() {
        if (this.chart) this.initChart();
      },
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.initChart();
    });
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$el, "macarons");
      this.chart.showLoading({
        maskColor: "rgba(255, 255, 255, .2)"
      });
      this.setOptions();
    },
    setOptions() {
      setTimeout(() => {
        this.chart.hideLoading();
        this.chart.setOption(this.chartOption);
      }, 1000);
    },
  },
};
</script>
View Code

 

2、页面尺寸改变时,改变图表尺寸的方法

import { debounce } from '@/utils'

export default {
  data() {
    return {
      $_sidebarElm: null,
      $_resizeHandler: null
    }
  },
  mounted() {
    this.initListener()
  },
  activated() {
    if (!this.$_resizeHandler) {
      // avoid duplication init
      this.initListener()
    }

    // when keep-alive chart activated, auto resize
    this.resize()
  },
  beforeDestroy() {
    this.destroyListener()
  },
  deactivated() {
    this.destroyListener()
  },
  methods: {
    // use $_ for mixins properties
    // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
    $_sidebarResizeHandler(e) {
      if (e.propertyName === 'width') {
        this.$_resizeHandler()
      }
    },
    initListener() {
      this.$_resizeHandler = debounce(() => {
        this.resize()
      }, 100)
 
      window.addEventListener('resize', this.$_resizeHandler)

      this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
      this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
    },
    destroyListener() {
      window.removeEventListener('resize', this.$_resizeHandler)
      this.$_resizeHandler = null

      this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
    },
    resize() {
      const { chart } = this
      chart && chart.resize()
    }
  }
}
View Code

3、防抖函数

/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce(func, wait, immediate) {
  let timeout, args, context, timestamp, result

  const later = function () {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp

    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last)
    } else {
      timeout = null
      // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args)
        if (!timeout) context = args = null
      }
    }
  }
View Code

4、组件使用,如下:

<!-- 产品排行 -->
<product-rank-top2 :chartOption="productRankTop2Option" />

5、echart 的配置项

const colorList = [
  {
    offset: 0,
    color: "#53639F",
  },
  {
    offset: 1,
    color: "#1F305D",
  },
];

const setBackgroundColor = ({
  type = "linear",
  x = 0,
  y = 0,
  x2 = 1,
  y2 = 1,
  colorStops = colorList,
} = {}) => {
  return {
    type,
    x,
    y,
    x2,
    y2,
    colorStops,
  };
};


  weekNewBadComplaintOption: {
        backgroundColor: setBackgroundColor(),
        title: {
          text: "新增不良投诉",
          left: "center",
          top: 10,
          textStyle: {
            color: "#fff",
          },
        },
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "cross",
            crossStyle: {
              color: "#999",
            },
          },
        },
        grid: {
          left: "5%",
          right: "5%",
        },
        dataZoom: [
          {
            type: "slider",
            show: true,
            start: 60,
            end: 100,
            textStyle: {
              color: "#fff"
            },
            handleSize: 20,
            handleStyle: {
              color: "#fff"
            },
            xAxisIndex: [0],
            filterMode: "filter"
          }
        ],
        xAxis: {
          type: "category",
          data: [],
          axisLabel: {
            textStyle: {
              color: "#fff"
            },
            formatter: (value, index) => {
              if(index > 25) {
                return "";
              } else {
                return value;
              }
            }
          },
          boundaryGap: false
        },
        yAxis: {
          type: "value",
          axisLabel: {
            color: "#fff",
          },
        },
        color: ["#5C9EDB"],
        series: [
          {
            data: [],
            type: "bar",
            barMinWidth: 50,
            barMaxWidth: 80,
            label: {
              show: true,
              position: "inside",
              color: "#f00",
            },
            showBackground: true,
            backgroundStyle: {
              color: "rgba(180, 180, 180, 0.2)",
            },
          },
        ],
      },
View Code