vue+echarts封装柱线图

前端可视化封装柱线图

  1. html
    这里没有用echarts自带的图例;自己写了一个所以出现了这么多html;
<template>
  <div class="barLineChart">
    <div ref="barLineChart" :style="{ width: `${width}px`, height: `${height}px` }" @mouseover="chartsMouseOver" @mouseout="chartsMouseOut"></div>
    <div class="legend" :style="{right:legendStyle}" v-show="showLegend">
      <div class="barlegend" v-if="legends.length && hasData">
        <div class="legendItem" v-for="(val, index) in legends" :key="index">
          <div class="block" :style="{ 'background-color': val.from }"></div>
          <div class="text" v-text="val.name"></div>
        </div>
      </div>
      <div class="linelegend" v-if="linelegends.length && hasLineData">
        <div class="legendItem" v-for="(val, index) in linelegends" :key="index">
          <div class="line" :style="{ 'background-color': val.color }"></div>
          <div class="text" v-text="val.name"></div>
        </div>
      </div>
    </div>
  </div>
</template>


  1. js**
<script>
export default {
  props: {
    height: { type: String, default: '100%' }, //高度
    width: { type: String, default: '100%' }, //宽度
    leftunit: { type: String, default: '个' }, //左侧单位
    rightunit: { type: String, default: '%' }, //右侧单位
    showJudge: { type: Boolean, default: true }, //y轴右侧是否显示
    rowData: {
      type: Array,
      default: () => {
        return [
          { legend: '类型1', measure: 152, dimension: '2016' },
          { legend: '类型1', measure: 101, dimension: '2017' },
          { legend: '类型1', measure: 90, dimension: '2018' },
          { legend: '类型1', measure: 101, dimension: '2019' },
          { legend: '类型1', measure: 152, dimension: '2020' },
          { legend: '类型1', measure: 101, dimension: '2021' },
        ];
      }
    },
    lineData: {
      type: Array,
      default: () => {
        return [
          { legend: '类型1', measure: 152, dimension: '2016' },
          { legend: '类型1', measure: 101, dimension: '2017' },
          { legend: '类型1', measure: 90, dimension: '2018' },
          { legend: '类型1', measure: 101, dimension: '2019' },
          { legend: '类型1', measure: 152, dimension: '2020' },
          { legend: '类型1', measure: 101, dimension: '2021' },
        ];
      }
    },
    showLegend: { type: Boolean, default: true }, //显示图例
    legends: {
      type: Array,
      default: () => {
        return [
          { name: "类型1", from: "#0095BF", to: "#0FC9FF" }
        ];
      }
    }, //图例数据
    linelegends: {
      type: Array,
      default: () => {
        return [{ name: '类型1', color: '#E3CF42' }];
      }
    }, //图例数据
    linestack: {
      type: Boolean,
      default: false
    }, //折线图是否堆积
    stack: {
      type: Boolean,
      default: true
    }, //是否堆积
    barWidth: {
      type: String,
      default: '10%'
    }, //柱子宽度
    gridTop: {
      type: String,
      default: '30%'
    },
    gridRight: {
      type: String,
      default: '3%'
    },
    gridLeft: {
      type: String,
      default: '0%'
    },
    gridBottom: {
      type: String,
      default: '10%'
    },
    active: {
      type: Boolean,
      default: false
    }, //是否交互
    activeobj: {
      type: String,
      default: ''
    }, //关联图层
    showToolTip: { type: Boolean, default: true }, //是否显示动画
    // x轴字体大小
    xAxisFontSize: {
      type: [Number, String],
      default: '17'
    },
    // y轴字体大小
    yAxisFontSize: {
      type: [Number, String],
      default: '17'
    },
    // 单位字体大小
    unitFontSize: {
      type: [Number, String],
      default: '16'
    },
    // x轴文字是否换行
    xWrap: {
      type: [Number, String], //是数字时为每行的显示字数,是字符时为以指定的字符为分隔符
      default: 0
    },
    // x文字是否倾斜
    axisLabelRotate: {
      type: [Number, String],
      default: 0
    },
    // x轴文字是否间隔显示
    xLabelInterval: {
      type: [Number, String],
      default: 'auto'
    },
    // 显示柱图顶部数据气泡
    showLabelBar: {
      type: Boolean,
      default: false
    },
    // 显示线图顶部数据气泡
    showLabelLine: {
      type: Boolean,
      default: false
    },
    // 显示y轴轴线
    showYaxisLine: {
      type: Boolean,
      default: true
    },
    // 显示X轴滚动条
    xScroll: {
      type: Boolean,
      default: false
    },
    //是否显示折线图
    isShowLine: {
      type: Boolean,
      default: true
    },
    // x轴显示个数
    dataZoomEnd: {
      type: Number,
      default: 1000
    },
    //图例距离右侧距离
    legendStyle:{
      type:String,
      default:'25%'
    }
  },
  data() {
    return {
      barLineChart: null,
      option: null,
      xData: [],
      yData: [],
      yData1: [],
      hasData: true,
      hasLineData: true,
      selectItemName: '', //选中柱子的名称
      isChangeColor: false //控制点击变色
    };
  },
  mounted() {
    let that = this;
    that.$nextTick(() => {
      if (that.rowData && that.lineData) {
        that.transformData(that.rowData);
        that.transformData1(that.lineData);
        that.drawChart();
        // that.tooltipShuffling();
      }
    });
  },
  methods: {
    chartsMouseOver() {
      clearInterval(this.setTime);
    },
    chartsMouseOut() {
      // this.tooltipShuffling();
    },
    drawChart() {
      var that = this;
      // 基于准备好的dom,初始化echarts实例
      this.barLineChart = this.$echarts.init(this.$refs.barLineChart);
      this.option = this.initOption();
      this.barLineChart.setOption(this.option, true);
      that.barLineChart.on('click', function(params) {
        if (that.active) {
          var selectObj = {};
          selectObj.activeObj = that.activeobj;
          //当前选中柱子
          if (that.selectItemName != params.name) {
            that.isChangeColor = true;
            that.selectItemName = params.name;
            selectObj.value = params;
          } else {
            that.isChangeColor = false;
            that.selectItemName = '';
            selectObj.value = null;
          }
          that.barLineChart.setOption(that.option, true);
          that.$eventBus.$emit('selectedMapPoint', selectObj);
        }
      });
    },
    initOption() {
      let that = this;
      if (!that.yData || (that.yData.length == 0 && !that.yData1) || that.yData1.length == 0) {
        that.option = {
          title: {
            text: `暂无数据`,
            show: true,
            textStyle: {
              align: 'center',
              color: '#fff',
              fontSize: 32
            },
            top: 'center',
            left: 'center'
          }
        };
        that.xData = [];
        that.hasData = false;
        that.hasLineData = false;
        return that.option;
      } else {
        that.hasData = true;
        that.hasLineData = true;
        that.option = {
          tooltip: {
            show: that.showToolTip,
            trigger: 'axis',
            textStyle: {
              fontSize: 18
            },
            axisPointer: {
              type: 'cross',
              animation: false,
              label: {
                backgroundColor: '#505765',
                fontSize: 18
              }
            }
          },
          grid: {
            left: that.gridLeft,
            right: that.gridRight,
            bottom: that.gridBottom,
            top: that.gridTop,
            containLabel: true
          },
          xAxis: [
            {
              type: 'category',
              axisTick: { show: false },
              data: this.xData,
              axisLine: {
                lineStyle: {
                  color: '#BFECFF'
                }
              },
              axisLabel: {
                color: '#BFECFF',
                fontSize: this.xAxisFontSize,
                rotate: this.axisLabelRotate,
                interval: this.xLabelInterval,
                formatter: function(params) {
                  if ((typeof that.xWrap).toLowerCase() === 'number') {
                    if (that.xWrap === 0) return params;
                    let length = params.length / that.xWrap;
                    let result = '';
                    for (let i = 0; i < length; i++) {
                      let start = i * that.xWrap;
                      let end = i + that.xWrap;
                      result += params.slice(start, end) + '\n';
                    }
                    return result;
                  } else {
                    let newArr = params.split(that.xWrap);
                    let resStr = '';
                    newArr.forEach((item, index) => {
                      if (index !== newArr.length - 1) {
                        resStr += `${item}\n${that.xWrap}`;
                      } else {
                        resStr += item;
                      }
                    });
                    return resStr;
                  }
                }
              }
            }
          ],
          yAxis: [
            {
              type: 'value',
              axisLine: {
                show: that.showYaxisLine,
                lineStyle:{
                  color: '#BFECFF',
                }
              },
              axisTick: {
                show: false,
              },
              axisLabel: {
                color: '#BFECFF',
                fontSize: this.yAxisFontSize
              },
              //隔行换色
              splitArea: {
                show: true,
                areaStyle: {
                  color: ['transparent', 'rgba(238,238,238,.1)']
                }
              },
              splitLine: {
                show: false
              }
            },
            {
              type: 'value',
              axisLine: {
                show: that.showYaxisLine,
                lineStyle:{
                  color: '#BFECFF',
                }
              },
              axisTick: {
                show: false,
              },
              show: this.showJudge,
              axisLabel: {
                color: '#BFECFF',
                fontSize: this.yAxisFontSize
              },
              //隔行换色
              splitArea: {
                show: false,
                areaStyle: {
                  color: ['transparent', 'rgba(238,238,238,.1)']
                }
              },
              splitLine: {
                show: false
              }
            }
          ],
          title: [
            {
              text: `${this.leftunit}`,
              padding: [5, 0, 0, 0],
              textStyle: {
                color: '#BFECFF',
                fontSize: this.unitFontSize,
                fontWeight: 400
              },
              top: 'top',
              left: 'left'
            },
            {
              text: `${this.rightunit}`,
              padding: [5, 5, 0, 0],
              textStyle: {
                color: '#BFECFF',
                fontSize: this.unitFontSize,
                fontWeight: 400
              },
              show: this.showJudge,
              top: 'top',
              left: 'right'
            }
          ],
          dataZoom: [
            {
              show: this.xScroll,
              height: 8,
              xAxisIndex: [0],
              bottom: 0,
              start: 0,
              end: that.dataZoomEnd,
              backgroundColor: 'rgba(41,53,91)',
              handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
              handleSize: '110%',
              handleStyle: {
                color: 'rgba(41,53,91)'
              },
              handleIconSize: 0,
              moveHandleStyle: {
                color: 'transparent'
              },
              textStyle: {
                color: '#fff'
              },
              borderColor: 'transparent'
            }
          ],
          series: []
        };
        that.option.xAxis[0].data = that.xData;
        that.option.series = [];
        that.yData.forEach((d, index) => {
          let serie = {
            type: 'bar',
            yAxisIndex: 0,
            data: d,
            barWidth: that.barWidth
          };
          serie.itemStyle = {
            normal: {
              color: function(params) {
                //判断选中的名字改变柱子的颜色样式
                if (that.isChangeColor && that.selectItemName === params.name) {
                  return new that.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    {
                      offset: 0.5,
                      color: '#FFFF00'
                    },
                    {
                      offset: 1,
                      color: '#00000000'
                    }
                  ]);
                } else {
                  return new that.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    {
                      offset: 0.5,
                      color: that.legends[index].from
                    },
                    {
                      offset: 1,
                      color: that.legends[index].to
                    }
                  ]);
                }
              }
            }
          };
          serie.label = {
            show: this.showLabelBar,
            position: 'top',
            padding: 3,
            borderColor: '#FFFFFF',
            borderWidth: 1,
            fontSize: 16,
            fontFamily: '微软雅黑',
            color: '#FFFFFF',
            backgroundColor: 'rgba(0,0,0,0.3)'
          };
          if (that.stack) {
            serie.stack = '0';
          }
          that.option.series.push(serie);
        });
        if (that.isShowLine) {
          that.yData1.forEach((d, index) => {
            let serie = {
              type: 'line',
              yAxisIndex: 1,
              data: d
            };
            serie.itemStyle = {
              normal: {
                color: that.linelegends[index].color
              }
            };
            serie.label = {
              show: this.showLabelLine,
              position: 'top',
              padding: 3,
              borderColor: '#FFFFFF',
              borderWidth: 1,
              fontSize: 16,
              fontFamily: '微软雅黑',
              color: '#FFFFFF',
              backgroundColor: 'rgba(0,0,0,0.3)'
            };

            if (that.linestack) {
              serie.stack = '0';
            }
            that.option.series.push(serie);
          });
        }
      }

      return that.option;
    },
    tooltipShuffling() {
      clearInterval(this.setTime);
      let count = 0;
      this.setTime = setInterval(() => {
        if (count == this.xData.length) {
          count = 0;
        }
        this.barLineChart.dispatchAction({
          type: 'showTip',
          seriesIndex: 0,
          dataIndex: count
        });
        count++;
      }, 1000);
    },
    transformData(rowData) {
      let that = this;
      //获取类别去重
      let dimensions = Array.from(
        new Set(
          rowData.map((r) => {
            return r.dimension;
          })
        )
      );
      that.xData = dimensions;
      that.yData = [];

      let legends = Array.from(
        new Set(
          rowData.map((r) => {
            return r.legend;
          })
        )
      );

      legends.forEach((l) => {
        let array = [];
        dimensions.forEach((d) => {
          let data = rowData.find((r) => r.dimension == d && r.legend == l);
          array.push(data.measure);
        });
        that.yData.push(array);
      });
    },
    transformData1(lineData) {
      let that = this;
      //获取类别去重
      let dimensions = Array.from(
        new Set(
          lineData.map((r) => {
            return r.dimension;
          })
        )
      );

      that.xData = dimensions;
      that.yData1 = [];

      let legends = Array.from(
        new Set(
          lineData.map((r) => {
            return r.legend;
          })
        )
      );

      legends.forEach((l) => {
        let array = [];
        dimensions.forEach((d) => {
          let data = lineData.find((r) => r.dimension == d && r.legend == l);
          array.push(data.measure);
        });
        that.yData1.push(array);
      });
    }
  },
  watch: {
    rowData: {
      handler(neVal) {
        let that = this;
        console.log('更新柱图数据');

        that.transformData(neVal);
        that.option = that.initOption(that.option);
        that.$nextTick(() => {
          that.yData.forEach((n, index) => {
            that.option.series[index].data = n;
          });
          that.yData1.forEach((n, index) => {
            that.option.series[index].data = n;
          });
          that.barLineChart.setOption(that.option);
        });
      },
      deep: false
    },
    lineData: {
      handler(neVal) {
        let that = this;
        console.log('更新折线图数据');
        that.transformData1(neVal);
        that.option = that.initOption(that.option);
        that.$nextTick(() => {
          that.yData1.forEach((n, index) => {
            that.option.series[index].data = n;
          });
          that.yData.forEach((n, index) => {
            that.option.series[index].data = n;
          });
          that.barLineChart.setOption(that.option);
        });
      },
      deep: false
    }
  },
  destroyed() {
    this.setTime && clearInterval(this.setTime);
    this.debounce && clearTimeout(this.debounce);
    this.barLineChart = null;
    this.option = null;
  }
};
</script>


3.css

<style lang="scss" scoped>
.barLineChart {
  width: 100%;
  position: relative;
  overflow: hidden;
  .legend {
    width: 100%;
    display: flex;
    position: absolute;
    top: 3px;
    right: 25%;
    justify-content: flex-end;
    line-height: 18px;

    .legendItem {
      display: flex;

      .block {
        width: 5px;
        height: 18px;
      }
      .text {
        margin: 0 5px;
        color: #bfebff;
        font-size: 16px;
      }
    }
  }
}
.barlegend {
  display: flex;
}
.linelegend {
  display: flex;
}
.line {
  width: 18px;
  height: 5px;
  margin-top: 4px;
}
</style>


其实大家可以去自己配置,自己想要的图表只是数据处理这块可能费点事,其余都还好,再说还有echars社区里面也有人提供了大量自己配置的图表。
社区链接:https://www.makeapie.com/explore.html

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值