echarts堆疊柱狀圖


最近寫了一個echarts堆疊柱狀圖頁面,因為經驗不是很多,寫個博客記錄一下

先貼代碼

<template>
  <div class="container-box">
    <div class="item-box">
      <div class="box" ref="clintBox">
        <div :id="chartsCode" :style="`width: ${width}px; height:400px;`"></div>
        <div class="tablebox">
          <table border="1px solid #000" class="mytable">
            <tr v-for="(item,index) in tableData" :key="index">
              <td width="100px" class="header" v-if="index === 0">
                <i class="poinit" style="background-color: #ffbb00"></i>
                {{'>' + '3年'}}
              </td>
              <td width="100px" class="header" v-if="index == 1">
                <i class="poinit" style="background-color: #a5a5a5"></i>
                {{'2-3年'}}
              </td>
              <td width="100px" class="header" v-if="index == 2">
                <i class="poinit" style="background-color: #ed7d31"></i>
                {{'1-2年'}}
              </td>
              <td width="100px" class="header" v-if="index == 3">
                <i class="poinit" style="background-color: #5b9bd5"></i>
                {{'0-1年'}}
              </td>
              <td v-for="(t) in item" :key="t" :width="filterWidth" class="mytd">{{t}}</td>
            </tr>
          </table>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'chartsCard',
  components: {
  },
  data () {
    return {
      option: [],
      roadNameList: [],
      tableData: [],
      width: 0,
    }
  },
  props: {
    data: {
      required: true,
    },
    code: {
      required: true,
    }
  },
  computed: {
    // 過濾路線名稱
    filterRoadName () {
      let arr = []
      this.data.forEach(item => {
        arr.push(item.roadCode)
      })
      this.roadNameList = arr
      return this.roadNameList
    },
    // 根據傳過來的數據長度動態計算表格的寬的
    filterWidth () {
      return (this.width - 300) / this.filterRoadName.length
    },
    // 獲取圖表容器的寬度
    chartsWith () {
      return this.$refs.clintBox.clientWidth
    },

    // 動態圖表id
    chartsCode () {
      return 'chart' + this.code
    }
  },
  watch: {
    data: function () {
      this.init()
    }
  },
  created () {
  },
  mounted () {
    this.$nextTick(() => {
      this.width = this.chartsWith
      setTimeout(() => {
        this.init()
      }, 200)
    })

  },
  methods: {

    init () {
      this.initChart()
      this.initTableData()

    },

    // 初始化echatrs
    initChart () {
      this.option = {
        tooltip: {
          trigger: "axis",
          formatter: '{b0}<br />{a0} : {c0}%<br/>{a1} : {c1}%<br/>{a2} : {c2}%<br/>{a3} : {c3}%',
        },
        grid: {
          // width: this.chartsWith * 0.8 + 'px',
          left: '150px',
          right: '150px',
          bottom: '25px',
        },
        xAxis: {
          show: true,
          data: this.filterRoadName,

          splitLine: {
            show: false,
          },
          axisTick: {
            show:true,
            length: 25, // 豎線的長度
            // interval:0

          }
        },
        yAxis: {
          max: 100,// 設置最大值是多少
          splitNumber: 10,// 設置分幾段顯示
          splitLine: {
            show: true,
          },
          axisTick: {
            show: false
          },
          axisLabel: {
            show: true,
            interval: 'auto',
            formatter: '{value} %',
          },

        },
        series: [{
          name: '0-1年',
          type: 'bar',
          stack: '使用情況',//相同的stack開啟堆疊
          // data: [60, 20, 36, 10, 10, 20],
          data: this.initData('year01Length'),
          barWidth: 50,//柱子寬度
          barGap: '0%',/*多個並排柱子設置柱子之間的間距*/
          barCategoryGap: '0%',/*多個並排柱子設置柱子之間的間距*/
          itemStyle: {
            normal: { color: "#009587" },
          }
        }, {
          name: '1-2年',
          type: 'bar',
          stack: '使用情況',//相同的stack開啟堆疊
          data: this.initData('year12Length'),
          barWidth: 50,//柱子寬度
          itemStyle: {
            normal: { color: "#2196f3" },
          }
        }, {
          name: '2-3年',
          type: 'bar',
          stack: '使用情況',//相同的stack開啟堆疊
          data: this.initData('year23Length'),
          barWidth: 50,//柱子寬度
          itemStyle: {
            normal: { color: "#ffeb3b" },
          }
        }, {
          name: '3-4年',
          type: 'bar',
          stack: '使用情況',//相同的stack開啟堆疊
          data: this.initData('year34Length'),
          barWidth: 50,//柱子寬度
          itemStyle: {
            normal: { color: "#9c27b0" },
          }
        }]
      }
      // 基於准備好的dom,初始化echarts實例
      let myChart = this.$echarts.init(document.getElementById(this.chartsCode))
      // 使用剛指定的配置項和數據顯示圖表。
      myChart.setOption(this.option, true)
      // myChart.resize()
    },

    // 初始化柱狀圖數據 計算每一個val在數據中和totalLength的百分比
    initData (val) {
      var serie = []
      this.data.forEach((item, index) => {
        let num = item[val]
        let total = 0
        let arr = [item.year01Length, item.year12Length, item.year23Length, item.year34Length]
        let arr1 = arr.filter(item => {
          if (item !== 'null') {
            return item
          }
        })
        arr1.forEach(item => {
          total += parseFloat(item)
        })
        //   // 計算占比
        var numcount = this.Percentage(num, parseFloat(total.toFixed(3)))
        serie.push(numcount)
      })
      return serie
    },

    //計算兩者占比方法
    Percentage (num, total) {
      return (Math.round(num / total * 10000) / 100.00)// 小數點后兩位百分比
    },

    // 初始化表格數據
    initTableData () {
      let tableArr = []
      console.log(this.data)
      for (let i = 0; i <= 3; i++) {
        let arr = []
        let str = ('year' + i) + (i + 1 + 'Length')
        this.data.forEach((item, index) => {
          arr.push(item[str])
        })
        tableArr.unshift(arr)
      }
      this.tableData = tableArr
    },

  },
}

</script>

<style scoped>
.el-carousel__item h3 {
  color: #475669;
  font-size: 18px;
  opacity: 0.75;
  line-height: 400px;
  margin: 0;
}
.el-carousel__item:nth-child(2n) {
  background-color: #f5f7fa;
}
.el-carousel__item:nth-child(2n + 1) {
  background-color: #f5f7fa;
}
.item-box {
  width: 100%;
  height: 100%;

  display: flex;
  justify-content: center;
  align-items: start;
}
.box {
  width: 100%;
  position: relative;
}
.tablebox {
  width: 100%;
  height: 300px;
}

.mytable {
  border-collapse: collapse;
  margin-left: 50px;
}
.mytable td {
  padding: 5px 10px;
  text-align: center;
}
.mytable .header {
  text-align: left;
}
.mytd {
  height: 25px !important;
}
.poinit {
  display: inline-block;
  width: 10px;
  height: 10px;
  vertical-align: middle;
  margin-right: 5px;
}
</style>

在echarts里option中的series的數組數據中我們可以通過stack屬性控制是否堆疊,當我們的兩個數據需要堆疊顯示時,我們只需要給他兩個的stack設置相同名稱就可以了!

實現等高的堆疊圖,需要對數據進行處理

修改 tooltip 顯示百分比

echarts提示框顯示百分比 數據已經轉換好了 只需在后面加%號

tooltip: {
          trigger: "axis",
          formatter: '{b0}<br />{a0} : {c0}%<br/>{a1} : {c1}%<br/>{a2} : {c2}%<br/>{a3} : {c3}%',
        },

實現底部表格參考

因為實現起來難度較大 所以采用的是elementui的table組件 通過給定option配置項grid:{left:'100px',right:'100px'}此時圖表距離canvas畫布左右均有100px的空間
canvas的寬度是100% 所以我們等通過this.$refs.fatherBox.clientWidth的方式獲取到canvas父盒子的寬度 然后減去左右空白距離(200)除以柱子個數計算屬性動態的計算出x軸分隔的寬度同時指定給表格的寬度結合定位調整表格的位置,大體上能實現這種效果

因為element-ui的表格不好實現 所以手寫的table表格 表格頂部與圖表對齊實現方式:圖表配置項里 grid:{left:'100px',right:'100px',bottom:'25px'}指定的是圖表相對於canvas的上下左右的距離 底部25px為x軸豎線的長度 表格的父容器和圖表的父容器寬度都是100% 給表格和圖表相同的左邊距即可
td的寬度通過計算屬性拿到圖表父容器的寬度 然后(父寬度 - 圖表的左右邊距)/ 柱狀圖的個數

碰到的小坑

子組件渲染echarts時父組件還沒有獲取到數據就渲染了子組件 這是傳過來的是空值 子組件也就無法顯示
解決方法:v-if="tableData.length !== 0" 判斷一下

watch里面調用methods方法不能使用箭頭函數 否則會報錯


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM