Echarts - barChart - Vue组件模板样式

一、引用方式:

 <bar-chart key="Chart"
               :yName="'Y'"
               :legend="data.legend"
               :xAxis="data.xAxis"
               :lineColors="data.colorList"
               :series="data.series"
               :tLabel="{show:false}"
               :axisLabFmt='true'
               :isMix="true"
               :width="430"
               :height="260"
               :axisLineClr="'#2a72c1'"
               :splitLineClr="'rgba(42,114,193,0.35)'"
               :grid="{top:40,bottom:60,left:30,right:10}"
               :axisLalClr="'#9dc4dd'"
               legCrl="#fff"
               :avPosition="'start'">
</bar-chart>

二、组件:

<template>
  <div :class="classes" :style="styles" ref="barChart"></div>
</template>
<script>
import eCharts from "echarts";

const prefixCls = "barChart";
export default {
  name: "barChart",
  props: {
    // 外盒宽度
    width: {
      type: [Number, String],
      default: 500
    },
    // 外盒高度
    height: {
      type: [Number, String],
      default: 300
    },
    // 图例
    legend: {
      type: Array,
      default() {
        return [];
      }
    },
    // 图例文字颜色
    legCrl: {
      type: String,
      default: "#000"
    },
    // 图例位置
    legPos: {
      type: String,
      default: "right",
      validator(value) {
        return oneOf(value, ["left", "center", "right"]);
      }
    },
    // 柱宽
    barWidth: {
      type: Number,
      default: 22
    },
    xAxis: {
      type: Array,
      default() {
        return [];
      }
    },
    //是否堆叠
    stack: {
      type: Boolean,
      default: false
    },
    // Y轴单位
    yName: String,
    // 折线Y轴的单位
    lineName: String,
    // X轴单位
    xName: String,
    // 是否增加右侧Y轴
    isY: {
      type: Boolean,
      default: false
    },
    // 是否隐藏所有线条和刻度
    isHidden: {
      type: Boolean,
      default: false
    },
    colorList: {
      type: Array,
      default() {
        return ["#25d4e7", "#fe6b40", "#6bb592"];
      }
    },
    series: {
      type: Array,
      default() {
        return [];
      }
    },
    // 图表数据太多需要使用的滚动条和缩放效果,设置这个之后需要设置gridBottom,让滚动条显示在数据下方
    isDataZoom: {
      type: Boolean,
      default: false
    },
    // 滚动条填充颜色
    zoomFillCrl: {
      type: String,
      default: "grey"
    },
    // 滚动条背景色
    zoomBgcCrl: {
      type: String,
      default: "#fff"
    },
    // 滚动条边框色
    zoomBorCrl: {
      type: String,
      default: "grey"
    },
    // 数据窗口范围的起始百分比
    zoomStart: {
      type: Number,
      default: 0
    },
    // 数据窗口范围的结束百分比
    zoomEnd: {
      type: Number,
      default: 50
    },
    // 整个图标的宽高,以及距上下左右的边距
    grid: {
      type: Object,
      default: function() {
        return {
          height: Number,
          width: Number,
          top: 30,
          bottom: 5,
          left: 10,
          right: 15,
          containLabel: true
        };
      }
    },
    // 定义X轴刻度的格式(文字太多设置换行)
    axisLabFmt: {
      type: Boolean,
      default: false
    },
    // 定义X轴刻度每行显示的字数,默认为2个
    wordsNum: Number,
    // 是否要给bar添加事件,以及事件类型
    barEvent: {
      type: Object,
      default() {
        return {
          eventType: "",
          callBack: null
        };
      }
    },
    // 是否需要柱状的背景色
    isBgc: {
      type: Boolean,
      default: false
    },
    // 与柱状图相对应的平均线
    avDataBar: {
      type: Array,
      default() {
        return [];
      }
    },
    // 与折线图相对应的平均线
    avDataLine: {
      type: Array,
      default() {
        return [];
      }
    },
    // 折线平均线颜色
    avLineCrl: {
      type: Array,
      default() {
        return ["#fe6b40", "#edea10"];
      }
    },
    // 柱子平均线颜色
    avBarCrl: {
      type: Array,
      default() {
        return ["#edea10", "#fe6b40"];
      }
    },
    // 如果柱状图需要显示所占百分比
    percent: {
      type: Boolean,
      default: false
    },
    // X轴Y轴刻度线颜色及文字背景色
    axisLineClr: {
      type: String,
      default: "#000"
    },
    // X轴Y轴的文字颜色
    axisLalClr: {
      type: String,
      default: "#000"
    },
    // 背景分割线颜色
    splitLineClr: {
      type: String,
      default: "#ddd"
    },
    // 更改图表展示类型
    changeDir: {
      type: Boolean,
      default: false
    },
    // 数据单位
    lUnit: String,
    // 设置图表label的是否显示,位置,颜色,内容
    tLabel: {
      type: Object,
      default: function() {
        return {
          show: true,
          position: "top",
          formatter: "{c}" + this.lUnit,
          textStyle: {
            color: "#000"
          }
        };
      }
    },
    //是否显示图例
    legShow: {
      type: Boolean,
      default: true
    },
    // 是否需要隔行变色
    isMix: {
      type: Boolean,
      default: false
    },
    // 柱状之间的距离
    barGap: {
      type: String | Number,
      default: "30%"
    },
    barCategoryGap: {
      type: String | Number,
      default: "20%"
    },
    // 如果是折柱混合,且柱子的颜色是隔行变色,则需单独设置line的颜色
    lineColors: {
      type: Array,
      default() {
        return ["#F6D37E"];
      }
    },
    // 平均线数字的位置
    avPosition: {
      type: String,
      default: "middle",
      validator(value) {
        return oneOf(value, ["start", "middle", "end"]);
      }
    },
    // 自定义Y轴刻度文字的样式
    yAxisLabel: {
      type: Object,
      default: function() {}
    },
    // Y轴方向的背景色
    splitBgc: {
      type: Array,
      default: function() {
        return ["rgba(0,0,0,0)"];
      }
    },
    // Y轴是否反向
    inverse: {
      type: Boolean,
      default: false
    },
    // Y轴刻度单位
    yUnit: {
      type: Array,
      default: function() {
        return ["", ""];
      }
    },
    // 多条折线是否堆叠
    lineStack: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      maxBar: [],
      splitLine: {
        lineStyle: {
          color: this.splitLineClr
        }
      },
      chart: null
    };
  },
  computed: {
    classes() {
      return `${prefixCls}`;
    },
    styles() {
      let style = {};
      if (this.height) {
        style.height = `${this.height}px`;
      }
      if (this.width) {
        style.width = `${this.width}px`;
      }
      return style;
    }
  },
  mounted() {
    setTimeout(() => {
      this.drawChart();
    }, 200);
  },
  updated() {
    this.$nextTick(() => {
      this.drawChart();
    });
  },
  watch: {
    series(curVal, oldVal) {
      this.drawChart();
    },
    colorList(curVal, oldVal) {
      this.drawChart();
    }
  },
  methods: {
    oneOf(value, validList) {
      for (let i = 0; i < validList.length; i++) {
        if (value === validList[i]) {
          return true;
        }
      }
      return false;
    },
    countMax(max) {
      const num = Math.ceil(max);
      let base = "1";
      const len = Math.abs(num).toString().length - 1;
      for (let i = 0; i < len; i++) {
        base += "0";
      }
      let maxNum = Math.ceil(parseFloat(num / parseInt(base))) * parseInt(base);
      if ((maxNum / parseInt(base)) % 3 != 0) {
        return Math.ceil(maxNum / parseInt(base) / 3) * 3 * parseInt(base);
      }
      return maxNum;
    },

    drawChart() {
      let series = [];
      let isMulti = false;
      let o = 0;
      this.series.forEach((item, index) => {
        let sum = 0;
        item.data.forEach(i => {
          sum = sum + parseInt(i);
        });
        const json = {
          name: this.legend[index],
          type: item.type,
          data: item.data,
          label: {
            normal: this.tLabel
          },
          barWidth: this.barWidth,
          symbol: "circle",
          barGap: this.barGap,

          barCategoryGap: this.barCategoryGap,
          symbolSize: 8,
          itemStyle: {
            normal: {
              color: params => {
                if (this.isMix) {
                  if (params.dataIndex % 2 === 0) {
                    return this.colorList[0];
                  } else {
                    return this.colorList[1];
                  }
                } else {
                  return this.colorList[index];
                }
              }
            }
          }
        };
        if (item.type === "line") {
          json.yAxisIndex = 1;
          json.stack = this.lineStack;
          json.lineStyle = {
            normal: {
              color: this.isMix ? this.lineColors[o] : this.colorList[index]
            }
          };
          json.itemStyle = {
            normal: {
              color: this.isMix ? this.lineColors[o++] : this.colorList[index]
            }
          };
          isMulti = true;
        }
        if (this.percent) {
          json.label = {
            normal: {
              show: true,
              position: "top",
              formatter: params => {
                return this.percent
                  ? parseInt((params.value / sum) * 100) + "%"
                  : "{c}";
              }
            }
          };
        }
        if (this.stack) {
          json.stack = "总量";
        }
        if (this.isBgc) {
          var jsonBgc = {};
          for (var attr in json) {
            jsonBgc[attr] = json[attr];
          }
          jsonBgc.barGap = "-100%";
          jsonBgc.label = { normal: { show: false } };
          jsonBgc.barWidth = this.barWidth;
          jsonBgc.silent = true;
          jsonBgc.tooltip = { show: false };
          //颜色需要有透明度
          jsonBgc.itemStyle = {
            normal: { color: "rgba(102, 102, 102,.2)" }
          };
          //计算柱状图背景高度
          let barMax = 0;
          json.data.forEach(item => {
            if (item >= barMax) {
              barMax = item;
            }
          });
          const num = this.countMax(barMax);
          this.maxBar = [];
          json.data.forEach(item => {
            this.maxBar.push(num);
          });
          //data填你需要的背景的值
          jsonBgc.data = this.maxBar;
          series.push(jsonBgc);
        }
        if (this.avDataBar || this.avDataLine) {
          let avData = [];
          let color = "";
          if (item.type === "bar") {
            this.avDataBar.forEach((item, index) => {
              avData.push({
                yAxis: item,
                lineStyle: {
                  normal: {
                    color: this.avBarCrl[index]
                  }
                }
              });
            });
            color = this.avBarCrl[index];
          } else {
            this.avDataLine.forEach((item, index) => {
              avData.push({
                yAxis: item,
                lineStyle: {
                  normal: {
                    color: this.avLineCrl[index]
                  }
                }
              });
            });
          }
          json.markLine = {
            data: avData,
            symbolSize: 0,
            lineStyle: {
              normal: {
                color: color,
                type: "solid",
                width: 2,
                position: "right"
              }
            },
            label: {
              normal: {
                position: this.avPosition
              }
            }
          };
        }
        series.push(json);
      });

      const option = {
        legend: {
          show: this.legShow,
          data: this.legend,
          textStyle: {
            color: this.legCrl
          },
          itemWidth: 12,
          itemHeight: 12
        },
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "cross",
            crossStyle: {
              color: "#999"
            }
          }
        },
        animationEasing: "sinusoidalInOut",
        animationDuration: 1500,
        grid: this.grid,
        xAxis: [
          {
            type: this.changeDir ? "value" : "category",
            axisLabel: {
              interval: 0,
              textStyle: {
                color: this.axisLalClr
              },
              show: this.changeDir ? false : true
            },
            axisLine: {
              lineStyle: {
                color: this.axisLineClr
              },
              show: this.changeDir ? false : true
            },
            axisTick: {
              show: false
            },
            data: this.changeDir ? "" : this.xAxis,
            splitLine: this.splitLine
          }
        ],
        yAxis: [
          {
            type: this.changeDir ? "category" : "value",
            data: this.changeDir ? this.xAxis : "",
            inverse: this.inverse,
            axisLabel: this.yAxisLabel
              ? this.yAxisLabel
              : {
                  interval: 0,
                  textStyle: {
                    color: this.axisLalClr
                  },
                  show: true,
                  formatter: "{value}" + this.yUnit[0]
                },
            axisLine: {
              lineStyle: {
                color: this.axisLineClr
              }
            },
            axisTick: {
              show: false
            },
            name: this.yName,
            nameTextStyle: {
              color: "#ffffff"
            },
            splitLine: this.splitLine,
            splitArea: {
              show: true,
              areaStyle: {
                color: this.splitBgc
              }
            },
            splitNumber: 3
          }
        ],
        series: series
      };
      // X轴的显示字数是否要换行
      if (this.axisLabFmt) {
        option.xAxis[0].axisLabel.formatter = params => {
          let newParamsName = "";
          let paramsNameNumber = params.length;
          let provideNumber = this.wordsNum ? this.wordsNum : 2;
          let rowNumber = Math.ceil(paramsNameNumber / provideNumber);
          if (paramsNameNumber > provideNumber) {
            for (let p = 0; p < rowNumber; p++) {
              let tempStr = "";
              let start = p * provideNumber;
              let end = start + provideNumber;
              if (p == rowNumber - 1) {
                tempStr = params.substring(start, paramsNameNumber);
              } else {
                tempStr = params.substring(start, end) + "\n";
              }
              newParamsName += tempStr;
            }
          } else {
            newParamsName = params;
          }
          return newParamsName;
        };
      }
      // 是否隐藏X和Y轴的刻度和线条
      if (this.isHidden) {
        option.xAxis[0] = {
          type: "category",
          axisLabel: {
            interval: 0,
            textStyle: {
              color: this.axisLalClr
            }
          },
          axisLine: { show: false },
          axisTick: { show: false },
          data: this.xAxis
        };
        option.yAxis[0] = {
          type: "value",
          axisLabel: { show: false },
          axisLine: { show: false },
          axisTick: { show: false },
          name: this.yName,
          nameTextStyle: {
            color: this.axisLalClr
          },
          splitLine: { show: false }
        };
      }
      // 是否需要右侧Y轴刻度
      if (isMulti && !this.isY) {
        option.yAxis.push({
          type: "value",
          splitNumber: 3,
          show: false,
          //              min: 0,
          //              max: 100,
          axisLabel: {
            inside: true
          }
        });
      } else if (this.isY) {
        option.yAxis.push({
          type: "value",
          splitNumber: 3,
          name: this.lineName,
          nameTextStyle: {
            color: this.axisLalClr
          },
          axisLine: {
            lineStyle: {
              color: this.axisLineClr
            }
          },
          axisTick: {
            show: false
          },
          splitLine: this.splitLine,
          axisLabel: {
            interval: 0,
            textStyle: {
              color: this.axisLalClr
            },
            formatter: "{value}" + this.yUnit[1]
          },
          formatter: "{value}%"
        });
      }
      // 图例位置
      switch (this.legPos) {
        case "left":
          option.legend.left = 15;
          break;
        case "center":
          break;
        case "right":
          option.legend.right = 15;
          break;
      }
      // 设置Y轴名字
      if (this.yName) {
        option.yAxis[0].name = this.yName;
        option.yAxis[0].nameTextStyle = {
          color: this.axisLalClr
        };
      }
      // 设置X轴名字
      if (this.xName) {
        option.xAxis[0].name = this.xName;
        option.xAxis[0].nameTextStyle = {
          color: this.axisLalClr
        };
        option.xAxis[0].nameLocation = "start";
        option.xAxis[0].nameGap = "20";
      }
      // 设置柱状背景色
      if (this.isBgc) {
        option.xAxis.push({
          type: "category",
          data: this.xAxis,
          tooltip: { show: false },
          axisLine: { show: false },
          axisTick: { show: false },
          axisLabel: { show: false },
          splitArea: { show: false },
          splitLine: { show: false }
        });
      }
      // 设置滚动条
      if (this.isDataZoom) {
        option.dataZoom = [
          {
            id: "dataZoomX",
            type: "slider",
            xAxisIndex: [0],
            filterMode: "weakFilter", // 设定为 'filter' 从而 X 的窗口变化会影响 Y 的范围。
            start: this.zoomStart ? this.zoomStart : 0,
            bottom: 10,
            end: this.zoomEnd ? this.zoomEnd : 50,
            height: 10,
            handleSize: 0,
            zoomLock: true,
            fillerColor: this.zoomFillCrl ? this.zoomFillCrl : "#114c91",
            backgroundColor: this.zoomBgcCrl ? this.zoomBgcCrl : "#434651",
            borderColor: this.zoomBorCrl ? this.zoomBorCrl : "rgba(0,0,0,0)",
            showDetail: false,
            showDataShadow: false
          },
          {
            type: "inside",
            xAxisIndex: [0],
            filterMode: "weakFilter",
            start: this.zoomStart ? this.zoomStart : 0,
            end: this.zoomEnd ? this.zoomEnd : 50
          }
        ];
      }
      this.chart = eCharts.init(this.$refs.barChart);
      this.chart.on(this.barEvent.eventType, this.barEvent.callBack);
      this.chart.setOption(option);
    }
  }
};
</script>
<style>
</style>

猜你喜欢

转载自www.cnblogs.com/amadoGrowers/p/12048391.html
今日推荐