echart 3d立体颜色渐变柱状图

如果可以实现记得点赞分享,谢谢老铁~

1.需求描述

根据业务需求将不同的法律法规,展示不同的3d立体渐变柱状图。

2.先看下效果图

echart 3d立体颜色渐变柱状图_第1张图片

3. 确定三面的颜色,这里我是自定义的颜色

   // 右面生成颜色
    const rightColorArr = ref([
      "#79DED1",
       ...
    ]);
    // 左面生成颜色
    const leftColorArr = ref([
      "#67C3B7", 
      ...
    ]);
    // 顶部生成颜色
    const topColorArr = ref([
      "#ADF4EB",
      ...
    ]);

4.然后绘画三个面对应的函数,且注册

// 绘制左侧面
    const CubeLeft = echarts.graphic.extendShape({
    });
    // 绘制右侧面
    const CubeRight = echarts.graphic.extendShape({
    });
    // 绘制顶面
    const CubeTop = echarts.graphic.extendShape({
    });
    // 注册三个面图形
    echarts.graphic.registerShape("CubeLeft", CubeLeft);
    echarts.graphic.registerShape("CubeRight", CubeRight);
    echarts.graphic.registerShape("CubeTop", CubeTop);

5.重点在renderItem 自定义渲染函数上

 series: [
          {
            type: "custom",
            renderItem: (params, api) => {
              let cubeLeftStyle: any = "";
              let cubeRightStyle: any = "";
              let cubeTopStyle: any = "";
              cubeLeftStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: leftColorArr.value[params.dataIndex],
                },
                {
                  offset: 1,
                  color: leftColorArr.value[params.dataIndex],
                },
              ]);
              cubeRightStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: rightColorArr.value[params.dataIndex],
                },
                {
                  offset: 1,
                  color: rightColorArr.value[params.dataIndex],
                },
              ]);
              cubeTopStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: topColorArr.value[params.dataIndex],
                },
                {
                  offset: 1,
                  color: topColorArr.value[params.dataIndex],
                },
              ]);
              const location = api.coord([api.value(0), api.value(1)]);
              return {
                type: "group",
                children: [
                  {
                    type: "CubeLeft",
                    shape: {
                      api,
                      xValue: api.value(0),
                      yValue: api.value(1),
                      x: location[0],
                      y: location[1],
                      xAxisPoint: api.coord([api.value(0), -80]),
                    },
                    style: {
                      fill: cubeLeftStyle,
                    },
                  },
                  {
                    type: "CubeRight",
                    shape: {
                      api,
                      xValue: api.value(0),
                      yValue: api.value(1),
                      x: location[0],
                      y: location[1],
                      xAxisPoint: api.coord([api.value(0), -80]),
                    },
                    style: {
                      fill: cubeRightStyle,
                    },
                  },
                  {
                    type: "CubeTop",
                    shape: {
                      api,
                      xValue: api.value(0),
                      yValue: api.value(1),
                      x: location[0],
                      y: location[1],
                      xAxisPoint: api.coord([api.value(0), -50]),
                    },
                    style: {
                      fill: cubeTopStyle,
                    },
                  },
                ],
              };
            },
            data: valList.value,
          },
        ],

5.最后看全文吧,这个是vue3 的文件

<template>
  <div class="topCon">
    <div class="tagList left">
      <div class="item" v-for="(item, index) in nameList" :key="index">
        <a-tag :color="rightColorArr[index]" class="tag"
          >TOP {{ index + 1 }}</a-tag
        >
        <span>{{ item }}</span>
      </div>
    </div>
    <div class="right" id="AnalysisLegalTopBar" style="height: 400px"></div>
  </div>
</template>
<script lang="ts">
import { onMounted, toRefs, ref, watch } from "vue";
import * as echarts from "echarts";
type EChartsOption = echarts.EChartsOption;
export default {
  props: {
    data: Array,
  },
  setup(props) {
    const { data } = toRefs<any>(props);
    const myChart = ref<any>(null);
    let valList = ref<any>([]);
    let nameList = ref<any>([]);

    // 右面生成颜色
    const rightColorArr = ref([
      "#79DED1",
      "#75D5AF",
      "#7FD991",
      "#78BF9D",
      "#95D3C9",
      "#84B5D3",
      "#7794C1",
      "#828AD0",
      "#7573D1",
      "#8057D1",
    ]);
    // 左面生成颜色
    const leftColorArr = ref([
      "#67C3B7",
      "#68C39F",
      "#68C27A",
      "#65AD8A",
      "#7BB8AE",
      "#76A6C3",
      "#6789BC",
      "#737ABE",
      "#5A58BC",
      "#7349C6",
    ]);
    // 顶部生成颜色
    const topColorArr = ref([
      "#ADF4EB",
      "#9BEBCC",
      "#9DE6AB",
      "#98DEBD",
      "#A1E5DA",
      "#9DC5DE",
      "#8CACDD",
      "#B0B5E6",
      "#7F7DD0",
      "#8057D1",
    ]);

    // 绘制左侧面
    const CubeLeft = echarts.graphic.extendShape({
      shape: {
        x: 0,
        y: 0,
      },
      buildPath: function (ctx: any, shape) {
        // 会canvas的应该都能看得懂,shape是从custom传入的
        const xAxisPoint = shape.xAxisPoint;
        const c0 = [shape.x + 7, shape.y];
        const c1 = [shape.x - 23, shape.y - 6];
        const c2 = [xAxisPoint[0] - 23, xAxisPoint[1] - 13];
        const c3 = [xAxisPoint[0] + 7, xAxisPoint[1]];
        ctx
          .moveTo(c0[0], c0[1])
          .lineTo(c1[0], c1[1])
          .lineTo(c2[0], c2[1])
          .lineTo(c3[0], c3[1])
          .closePath();
      },
    });
    // 绘制右侧面
    const CubeRight = echarts.graphic.extendShape({
      shape: {
        x: 0,
        y: 0,
      },
      buildPath: function (ctx: any, shape) {
        const xAxisPoint = shape.xAxisPoint;
        const c1 = [shape.x + 7, shape.y];
        const c2 = [xAxisPoint[0] + 7, xAxisPoint[1]];
        const c3 = [xAxisPoint[0] + 25, xAxisPoint[1] - 15];
        const c4 = [shape.x + 25, shape.y - 15];
        ctx
          .moveTo(c1[0], c1[1])
          .lineTo(c2[0], c2[1])
          .lineTo(c3[0], c3[1])
          .lineTo(c4[0], c4[1])
          .closePath();
      },
    });
    // 绘制顶面
    const CubeTop = echarts.graphic.extendShape({
      shape: {
        x: 0,
        y: 0,
      },
      buildPath: function (ctx: any, shape) {
        const c1 = [shape.x + 7, shape.y];
        const c2 = [shape.x + 25, shape.y - 15]; //右点
        const c3 = [shape.x - 5, shape.y - 20];
        const c4 = [shape.x - 23, shape.y - 6];
        ctx
          .moveTo(c1[0], c1[1])
          .lineTo(c2[0], c2[1])
          .lineTo(c3[0], c3[1])
          .lineTo(c4[0], c4[1])
          .closePath();
      },
    });
    // 注册三个面图形
    echarts.graphic.registerShape("CubeLeft", CubeLeft);
    echarts.graphic.registerShape("CubeRight", CubeRight);
    echarts.graphic.registerShape("CubeTop", CubeTop);

    const getOption = () => {
      return {
        backgroundColor: "transparent",
        title: {
          // text: "单位:个",
          textStyle: {
            color: "#79DED1",
            fontWeight: "800",
            fontSize: 16,
          },
          left: "18px",
          top: "1%",
        },
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "shadow",
          },
          formatter: function (params, ticket, callback) {
            const item = params[1];
            return item.name + " : " + item.value;
          },
        },
        grid: {
          top: "12%",
          bottom: "3%",
          left: "left",
          containLabel: true,
        },
        xAxis: {
          type: "category",
          show: false,
          data: nameList.value,
          axisLine: {
            show: true,
            lineStyle: {
              color: "#7ebaf2",
            },
          },
          axisTick: {
            show: false,
            length: 9,
            alignWithLabel: true,
            lineStyle: {
              color: "#7DFFFD",
            },
          },
          axisLabel: {
            fontSize: 12,
          },
        },
        yAxis: {
          type: "value",
          show: false,
          min: 0,
          axisLine: {
            show: true,
            lineStyle: {
              color: "#7ebaf2",
            },
          },
          splitLine: {
            show: false,
          },
          splitArea: {
            show: true,
            areaStyle: {
              color: ["rgba(26,50,83,1)", "rgba(30,57,92,1)"],
            },
          },
          axisTick: {
            show: false,
          },
          axisLabel: {
            fontSize: 12,
          },
          boundaryGap: ["20%", "20%"],
        },
        series: [
          {
            type: "custom",
            renderItem: (params, api) => {
              let cubeLeftStyle: any = "";
              let cubeRightStyle: any = "";
              let cubeTopStyle: any = "";
              cubeLeftStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: leftColorArr.value[params.dataIndex],
                },
                {
                  offset: 1,
                  color: leftColorArr.value[params.dataIndex],
                },
              ]);
              cubeRightStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: rightColorArr.value[params.dataIndex],
                },
                {
                  offset: 1,
                  color: rightColorArr.value[params.dataIndex],
                },
              ]);
              cubeTopStyle = new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: topColorArr.value[params.dataIndex],
                },
                {
                  offset: 1,
                  color: topColorArr.value[params.dataIndex],
                },
              ]);
              const location = api.coord([api.value(0), api.value(1)]);
              return {
                type: "group",
                children: [
                  {
                    type: "CubeLeft",
                    shape: {
                      api,
                      xValue: api.value(0),
                      yValue: api.value(1),
                      x: location[0],
                      y: location[1],
                      xAxisPoint: api.coord([api.value(0), -80]),
                    },
                    style: {
                      fill: cubeLeftStyle,
                    },
                  },
                  {
                    type: "CubeRight",
                    shape: {
                      api,
                      xValue: api.value(0),
                      yValue: api.value(1),
                      x: location[0],
                      y: location[1],
                      xAxisPoint: api.coord([api.value(0), -80]),
                    },
                    style: {
                      fill: cubeRightStyle,
                    },
                  },
                  {
                    type: "CubeTop",
                    shape: {
                      api,
                      xValue: api.value(0),
                      yValue: api.value(1),
                      x: location[0],
                      y: location[1],
                      xAxisPoint: api.coord([api.value(0), -50]),
                    },
                    style: {
                      fill: cubeTopStyle,
                    },
                  },
                ],
              };
            },
            data: valList.value,
          },
          {
            type: "bar",
            label: {
              normal: {
                show: true,
                position: "top",
                fontSize: 16,
                color: "#6C6C6C",
                offset: [2, -25],
              },
            },
            itemStyle: {
              color: "transparent",
            },
            tooltip: {},
            data: valList.value,
          },
        ],
      };
    };

    watch(
      () => data.value,
      (list) => {
        let option_bar: any = getOption();
        list.forEach((item, index) => {
          nameList.value.push(item.name);
          valList.value.push(item.value);
        });
        option_bar && myChart.value.setOption(option_bar);
      }
    );
    onMounted(() => {
      // 基于准备好的dom,初始化echarts实例
      var chartDom: any = document.getElementById("AnalysisLegalTopBar");
      myChart.value = echarts.init(chartDom);

      window.addEventListener("resize", () => {
        myChart.value.resize();
      });
    });

    return {
      nameList,
      rightColorArr,
    };
  },
};
</script>
<style lang="less" scoped>
.topCon {
  display: flex;
  justify-content: center;
  align-items: center;
  .left {
    width: 30%;
    .item {
      display: flex;
      align-items: center;
    }
  }
  .right {
    width: 70%;
  }
  .tagList {
    .tag {
      width: 46px;
      height: 23px;
      border-radius: 4px;
      font-size: 10px;
      font-weight: 500;
      line-height: 20px;
      margin: 4px 0px;
      margin-right: 10px;
      color: #fff;
      background: rgba(121, 222, 209, 0.39);
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }
}
</style>

收工!谢谢老铁们的点赞收藏~

你可能感兴趣的:(vue,echart,3d,立体渐变柱状图)