Echarts-3D柱状图

通过Echarts的echarts.graphic.extendShape实现真正的3D柱状图

思路就是通过调整顶部面(CubeTop)、左侧面(CubeLeft)、右侧面(CubeRight)来决定柱状图的宽窄

建议优先调整顶部面,一般c1不需要动

javascript 复制代码
// echarts-3D-bar-config.js
import Vue from "vue";

const echarts = Vue.prototype.echarts;

const CubeLeft = echarts.graphic.extendShape({
  shape: {
    x: 0,
    y: 0
  },
  buildPath: function (ctx, shape) {
    const xAxisPoint = shape.xAxisPoint;
    // 顶部右侧顶点
    const c1 = [shape.x, shape.y];
    // 顶部左侧顶点
    const c2 = [shape.x - 15, shape.y - 8];
    // 底部左侧
    const c3 = [xAxisPoint[0] - 15, xAxisPoint[1] - 8];
    // 底部右侧
    const c4 = [xAxisPoint[0], xAxisPoint[1]];
    ctx.moveTo(c1[0], c1[1]).lineTo(c2[0], c2[1]).lineTo(c3[0], c3[1]).lineTo(c4[0], c4[1]).closePath();
  }
});

const CubeRight = echarts.graphic.extendShape({
  shape: {
    x: 0,
    y: 0
  },
  buildPath: function (ctx, shape) {
    const xAxisPoint = shape.xAxisPoint;
    // 顶部左侧顶点
    const c1 = [shape.x, shape.y];
    // 底部左侧顶点
    const c2 = [xAxisPoint[0], xAxisPoint[1]];
    // 底部右侧顶点
    const c3 = [xAxisPoint[0] + 15, xAxisPoint[1] - 8];
    // 顶部右侧顶点
    const c4 = [shape.x + 15, shape.y - 8];
    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, shape) {
    // 底部顶点
    const c1 = [shape.x, shape.y];
    // 右侧顶点
    const c2 = [shape.x + 15, shape.y - 8];
    // 顶部顶点
    const c3 = [shape.x, shape.y - 15];
    // 右侧顶点
    const c4 = [shape.x - 15, shape.y - 8];
    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);

然后在build-bar-option中引用即可

这里主要就是把series中的内容复制过来直接用就行了

javascript 复制代码
import Vue from "vue";
import "./echarts-3D-Bar-config"

const echarts = Vue.prototype.echarts;

export function buildBarOption(vm, xData = [], seriesData = [], originData = []) {
  const option = {
    xAxis: {
      type: "category",
      axisLabel: {
        color: "#fff",
        rotate: 45,
        fontSize: 10
      },
      axisTick: {
        show: false
      },
      axisLine: {
        show: true,
        lineStyle: {
          color: "rgb(53, 179, 229)",
          width: 2
        }
      },
      data: xData
    },
    tooltip: {
      trigger: "item",
      axisPointer: {
        type: "shadow",
        label: {
          show: true
        }
      },
      backgroundColor: "transparent",
      padding: 0,
      formatter: function (params) {
        // console.log(params)
        return `
            <div style="padding: 15px; background: linear-gradient(180.00deg, rgb(3, 36, 76),rgb(19, 36, 127) 100%)">
              <p>test</p>     
            </div>
        `;
      }
    },
    grid: {
      left: "15",
      bottom: "10",
      right: "10",
      top: "40",
      containLabel: true
    },
    yAxis: {
      type: "value",
      axisLabel: {
        color: "#fff"
      },
      splitLine: {
        show: true,
        lineStyle: {
          type: "dotted",
          color: "rgb(53, 179, 229)"
        }
      }
    },
    series: [
      {
        type: "custom",
        renderItem: (params, api) => {
          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), 0])
                },
                style: {
                  fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    {
                      offset: 0,
                      color: "#3B80E2"
                    },
                    {
                      offset: 1,
                      color: "#49BEE5"
                    }
                  ])
                }
              },
              {
                type: "CubeRight",
                shape: {
                  api,
                  xValue: api.value(0),
                  yValue: api.value(1),
                  x: location[0],
                  y: location[1],
                  xAxisPoint: api.coord([api.value(0), 0])
                },
                style: {
                  fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    {
                      offset: 0,
                      color: "#3B80E2"
                    },
                    {
                      offset: 1,
                      color: "#49BEE5"
                    }
                  ])
                }
              },
              {
                type: "CubeTop",
                shape: {
                  api,
                  xValue: api.value(0),
                  yValue: api.value(1),
                  x: location[0],
                  y: location[1],
                  xAxisPoint: api.coord([api.value(0), 0])
                },
                style: {
                  fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    {
                      offset: 0,
                      color: "#3B80E2"
                    },
                    {
                      offset: 1,
                      color: "#49BEE5"
                    }
                  ])
                }
              }
            ]
          };
        },
        data: seriesData
      },
      {
        data: seriesData,
        type: "bar",
        barWidth: 13,
        itemStyle: {
          color: "transparent"
        }
      }
    ]
  };

  return option;
}
相关推荐
Insseals2 小时前
因斯特浮动模块快速接头✨五大核心优势
前端
苏州邦恩精密2 小时前
2026江苏GOM三维扫描仪定制厂家找哪家?企业数字化转型视角
人工智能·机器学习·3d·自动化·制造
沐土Arvin2 小时前
港澳台行政区域json
前端
程序员鱼皮3 小时前
我花 300 块,让 Claude Fable 5 开发桌面 APP,值么?
前端
William_Xu3 小时前
JavaScript 并发控制
前端
拾年2753 小时前
从零手写 Ajax:用原生 XHR 搭建前后端交互全流程
前端·javascript·ajax
光影少年3 小时前
懒加载与分包:React.lazy + Suspense
前端·react.js·掘金·金石计划
Zldaisy3d3 小时前
面向LPBF过程监测的物理引导多源数据融合模型:从数据生成到熔化状态识别
3d
小林ixn3 小时前
你以为你懂 + 号?看完这篇 Bun + TS 实战,才发现以前全写错了
前端·javascript·typescript
namexingyun3 小时前
开源前端生态如何成为 AI UI 生成的“燃料“:shadcn/ui、Tailwind CSS、Storybook 技术价值全解剖
java·前端·人工智能·python·ui·开源·ai编程