Vue中使用Echarts实现立体柱状图(长方体)

预览:

代码:
页面部分:

<template>
  <div class="roadnum-all" ref="roadnumall">
    <div id="roadnum" ref="dom"></div>
  </div>
</template>

CSS部分:

.roadnum-all {
  width: 100%;
  height: 100%;      /*填满父级容器*/
}

JS部分:

import echarts from 'echarts'            // 引入Echarts

export default {
  name: "ltzzt",
  data() {
    return {
      data: [],
      dom: null
    }
  },
  mounted() {
    this.$nextTick(() => {      // 给图标宽高 使图标填满容器
      document.getElementById('roadnum').style.width = this.$refs.roadnumall.offsetWidth + 'px';
      document.getElementById('roadnum').style.height = this.$refs.roadnumall.offsetHeight + 'px';
      this.draw();
    })
  },
  methods: {
    // 画图
    draw() {
      // 网络请求 假装从后端拿回来的数据
      this.data = [
        { name: '京哈高速', value: 10 },
        { name: '京哈高速1', value: 20 },
        { name: '京哈高速2', value: 30 },
        { name: '京哈高速3', value: 40 },
        { name: '京哈高速4', value: 50 },
        { name: '京哈高速5', value: 60 },
        { name: '京哈高速6', value: 70 },
        { name: '京哈高速7', value: 80 },
        { name: '京哈高速8', value: 90 },
        { name: '京哈高速9', value: 100 },
        { name: '京哈高速10', value: 110 },
        { name: '京哈高速11', value: 120 }
      ];
      // 拼轴显示和数据的数组
      let xAxisText = [];
      let dataList = [];
      this.data.forEach(item => {
        xAxisText.push(item.name);
        dataList.push(item.value)
      })
      // 从这里开始 创建自定义图形 —— 长方体的正面
      var MyCubeRect = echarts.graphic.extendShape({
        shape: {
          x: 0,
          y: 0,
          width: 180,      // 长方体宽度
          zWidth: 8,      // 阴影折角宽
          zHeight: 4      // 阴影折角高
        },
        buildPath: function (ctx, shape) {
          console.log(ctx, shape);
          const api = shape.api;
          const xAxisPoint = api.coord([shape.xValue, 0]);
          const p0 = [shape.x, shape.y];
          const p1 = [shape.x - shape.width / xAxisText.length, shape.y];
          const p4 = [shape.x + shape.width / xAxisText.length, shape.y];
          const p2 = [xAxisPoint[0] - shape.width / xAxisText.length, xAxisPoint[1]];
          const p3 = [xAxisPoint[0] + shape.width / xAxisText.length, xAxisPoint[1]];

          ctx.moveTo(p0[0], p0[1]); //0
          ctx.lineTo(p1[0], p1[1]); //1
          ctx.lineTo(p2[0], p2[1]); //2
          ctx.lineTo(p3[0], p3[1]); //3
          ctx.lineTo(p4[0], p4[1]); //4
          ctx.lineTo(p0[0], p0[1]); //0
          ctx.closePath();
        }
      })

      // 创建第二个自定义图形 —— 长方体的上面和侧面
      var MyCubeShadow = echarts.graphic.extendShape({
        shape: {
          x: 0,
          y: 0,
          width: 180,
          zWidth: 8,
          zHeight: 4
        },
        buildPath: function (ctx, shape) {
          const api = shape.api;
          const xAxisPoint = api.coord([shape.xValue, 0]);
          const p0 = [shape.x, shape.y];
          const p1 = [shape.x - shape.width / xAxisText.length, shape.y];
          const p4 = [shape.x + shape.width / xAxisText.length, shape.y];
          const p6 = [shape.x + shape.width / xAxisText.length + shape.zWidth, shape.y - shape.zHeight];
          const p7 = [shape.x - shape.width / xAxisText.length + shape.zWidth, shape.y - shape.zHeight];
          const p3 = [xAxisPoint[0] + shape.width / xAxisText.length, xAxisPoint[1]];
          const p5 = [xAxisPoint[0] + shape.width / xAxisText.length + shape.zWidth, xAxisPoint[1] - shape.zHeight];

          ctx.moveTo(p4[0], p4[1]); //4
          ctx.lineTo(p3[0], p3[1]); //3
          ctx.lineTo(p5[0], p5[1]); //5
          ctx.lineTo(p6[0], p6[1]); //6
          ctx.lineTo(p4[0], p4[1]); //4

          ctx.moveTo(p4[0], p4[1]); //4
          ctx.lineTo(p6[0], p6[1]); //6
          ctx.lineTo(p7[0], p7[1]); //7
          ctx.lineTo(p1[0], p1[1]); //1
          ctx.lineTo(p4[0], p4[1]); //4
          ctx.closePath();
        }
      });
      echarts.graphic.registerShape('MyCubeRect', MyCubeRect);
      echarts.graphic.registerShape('MyCubeShadow', MyCubeShadow);
      const option = {
        color: ['#33b56a', '#fdcf5c', '#4c90ff', '#fe7b7a', '#69ccf6', '#a38bf8', '#ff9561', '#8cb0ea', '#fe81b4', '#ffb258'],
        title: {
          text: '验算路线排行榜',
          left: 20,
          top: 20
        },
        legend: {
          show: true,
          top: 25
        },
        grid: {
          left: '3%',
          right: '4%',
          top: '15%',
          bottom: '3%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          data: xAxisText,
          boundaryGap: true,
          interval: 0,
          axisLabel: {
            color: '#333',
            //  让x轴文字方向为竖向
            interval: 0,
            formatter: function (value) {
              return value.split('').join('\n')
            }
          }
        },
        yAxis: {
          type: 'value'
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow'
          },
        },
        series: [{
          name: '次数',
          type: 'custom',
          renderItem: (params, api) => {
            let location = api.coord([api.value(0), api.value(1)]);
            return {
              type: 'group',
              children: [{
                type: 'MyCubeRect',
                shape: {
                  api,
                  xValue: api.value(0),
                  yValue: api.value(1),
                  x: location[0],
                  y: location[1]
                },
                style: api.style(),      // api.style()——继承原本的样式
              }, {
                type: 'MyCubeShadow',
                shape: {
                  api,
                  xValue: api.value(0),
                  yValue: api.value(1),
                  x: location[0],
                  y: location[1]
                },
                style: {
                  fill: api.style(),
                  text: ''            // 继承原本样式的基础上将label清空 如果不清空生成的图上会显示两个重叠的label
                }
              }]
            }
          },
          stack: '总量',
          label: {
            show: true,
            position: 'top',
            color: '#333',
            formatter: `{c}次`,
            fontSize: 16,
            distance: 15
          },
          itemStyle: {
            normal: {
              color: (params) => {
                // 使每根柱子颜色都不一样 
                let colorList = ['#33b56a', '#fdcf5c', '#4c90ff', '#fe7b7a', '#69ccf6', '#a38bf8', '#ff9561', '#8cb0ea', '#fe81b4', '#ffb258'];
                if (params.dataIndex + 1 <= colorList.length) {
                  return colorList[params.dataIndex]
                } else {
                  // 如果柱子的数量超过颜色数组 就从头再来一遍
                  return colorList[params.dataIndex - colorList.length]
                }
              }
            }
          },
          data: dataList
        }]
      };
      this.dom = echarts.init(this.$refs.dom);
      this.dom.setOption(option, true)
      window.addEventListener("resize", () => {
        if (document.getElementById('roadnum') && this.$refs.roadnumall) {
          document.getElementById('roadnum').removeAttribute('_echarts_instance_');
          document.getElementById('roadnum').style.width = this.$refs.roadnumall.offsetWidth + 'px';
          document.getElementById('roadnum').style.height = this.$refs.roadnumall.offsetHeight + 'px';
          this.dom.resize();
        }
      });
    }
  }
}
posted @ 2020-08-17 16:01  仲夏今天也在写前端  阅读(4662)  评论(4编辑  收藏  举报