3d柱状图

描述:当前是关于Echarts图表中的 示例。
 
            const LinearGradientColor = {
  0: {
    left: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: '#87F4FD',
      },
      {
        offset: 1,
        color: '#67A8FF',
      },
    ]),
    right: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: '#6AC3CB',
      },
      {
        offset: 1,
        color: '#5280BF',
      },
    ]),
    top: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: '#87F4FD',
      },
      {
        offset: 0.5,
        color: '#69ACFF',
      },
      {
        offset: 1,
        color: '#67A8FF',
      },
    ]),
  },
  1: {
    left: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: '#A5DDE1',
      },
      {
        offset: 1,
        color: '#FFFFFF',
      },
    ]),
    right: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: '#A5DDE1',
      },
      {
        offset: 1,
        color: '#FFFFFF',
      },
    ]),
    top: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: '#A5DDE1',
      },
      // {
      //   offset: 0.5,
      //   color: '#69ACFF',
      // },
      {
        offset: 1,
        color: '#FFFFFF',
      },
    ]),
  },
  2: {
    left: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: '#FFBD0A',
      },
      {
        offset: 1,
        color: '#9F7503',
      },
    ]),
    right: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: '#FFBD0A',
      },
      {
        offset: 1,
        color: '#9F7503',
      },
    ]),
    top: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: '#FFE6A4',
      },
      {
        offset: 1,
        color: '#FFBD0A',
      },
    ]),
  },
}

const offsetX = 10 // 10 面宽度
const offsetY = 5 // 5 倾斜度
const offsetYY = 10 // 柱形整体下移距离
// 绘制左侧面
const CubeLeft = echarts.graphic.extendShape({
  shape: {
    x: 0,
    y: 0,
  },
  buildPath: function (ctx, shape) {
    const xAxisPoint = shape.xAxisPoint
    const yBase = shape.yBase

    const c0 = [shape.x, shape.y + yBase] // t-r
    const c1 = [shape.x - offsetX, shape.y - offsetY + yBase] // t-l
    const c2 = [xAxisPoint[0] - offsetX, xAxisPoint[1] - offsetY + yBase] // b-l
    const c3 = [xAxisPoint[0], xAxisPoint[1] + yBase] // b-r
    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, shape) {
    const xAxisPoint = shape.xAxisPoint
    const yBase = shape.yBase
    const c1 = [shape.x, shape.y + yBase]
    const c2 = [xAxisPoint[0], xAxisPoint[1] + yBase]
    const c3 = [xAxisPoint[0] + offsetX, xAxisPoint[1] - offsetY + yBase]
    const c4 = [shape.x + offsetX, shape.y - offsetY + yBase]
    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) {
    if (shape.yValue == 0) return
    const yBase = shape.yBase
    const c1 = [shape.x, shape.y + yBase]
    const c2 = [shape.x + offsetX, shape.y - offsetY + yBase] //右点
    const c3 = [shape.x, shape.y - offsetX + yBase]
    const c4 = [shape.x - offsetX, shape.y - offsetY + yBase]
    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 calcSuperpositionVal = (params, api, yData) => {
  const currentSeriesIndices = api.currentSeriesIndices()
  const seriesIndex = params.seriesIndex
  if (seriesIndex == 0 || currentSeriesIndices.length == 1 || currentSeriesIndices[0] === seriesIndex) return offsetYY
  const dataIndex = params.dataIndex
  const seriesData = yData.map(x => x[dataIndex])
  const yBaseNum = currentSeriesIndices.reduce((pre, cur) => {
    if (cur < seriesIndex) {
      pre = pre + seriesData[cur]
    }
    return pre
  }, 0)
  const chazhi = api.coord([0, yBaseNum])[1] - api.coord([0, 0])[1] + offsetYY
  return params.seriesIndex > 0 ? chazhi : offsetYY
}

const axisColor = 'rgba(211,228,242,0.6)'
  const markTextColor = '#D3E4F2'
  const splitLineColor = 'rgba(211,228,242,0.16)'
  const marks = [
    { name: '已消缺', color: '#68BEFE' },
    { name: '已忽略', color: '#DDFDFF' },
    { name: '未消缺', color: '#FFBD0A' },
  ]
  const arr = [
      { wxqslY: 0, x: '0', xStr: '#1主变', yxqslY: 1, yhlslY: 5 },
      { wxqslY: 1, x: '1', xStr: '110kV断路器', yxqslY: 0, yhlslY: 6 },
      { wxqslY: 5, x: '2', xStr: '35kV断路器', yxqslY: 5, yhlslY: 5 },
      { wxqslY: 3, x: '3', xStr: '10kV断路器', yxqslY: 1, yhlslY: 5 },
    ]
  const x = [],
    y = [[], [], []]

  for (const i of arr) {
    x.push(i.xStr)
    y[0].push(i.yxqslY) // 已消缺数量
    y[1].push(i.yhlslY) // 已忽略数量
    y[2].push(i.wxqslY) // 未消缺数量
  }
option = {
    title: {
      left: '2%',
      top: '-8%',
      subtext: '台',
      subtextStyle: {
        fontSize: 14,
        color: axisColor,
      },
    },
    grid: {
      show: true,
      left: '2%',
      bottom: '8%',
      top: '16%',
      right: 0,
      borderWidth: 0,
      backgroundColor: '#081532',
      containLabel: true,
      // 不支持渐变
      // backgroundColor: 'linear-gradient(to top, rgba(46,124,255,0.3), rgb(235,243,250,0.1))',
    },
    legend: {
      show: true,
      top: 0,
      right: 0,
      itemWidth: 8,
      itemHeight: 8,
      itemGap: 14,
      icon: 'circle',
      textStyle: {
        color: markTextColor,
        fontSize: 14,
      },
      data: marks.map(i => {
        return {
          name: i.name,
          itemStyle: { color: i.color },
        }
      }),
    },
    tooltip: {
      trigger: 'axis',
    },
    xAxis: {
      type: 'category',
      data: x,
      axisLabel: {
        color: axisColor,
        fontSize: 14,
        margin: 15,
        interval: 0,
      },
      axisTick: {
        show: false,
      },
    },
    yAxis: {
      type: 'value',
      axisLabel: {
        color: axisColor,
        fontSize: 14,
        margin: 14,
      },
      axisLine: {
        show: true,
        lineStyle: {
          color: splitLineColor,
        },
      },
      min: 0,
      minInterval: 1,
      splitLine: {
        lineStyle: {
          color: splitLineColor,
        },
      },
    },
    series: marks.map((i, j) => {
      return {
        type: 'custom',
        name: i.name,
        stack: 'Ad',
        color: i.color,
        // emphasis: {
        // 	focus: 'series'
        // },
        renderItem: (params, api) => {
          const location = api.coord([api.value(0), api.value(1)])
          const yBase = calcSuperpositionVal(params, api, y)
          const xAxisPoint = api.coord([api.value(0), 0])
          return {
            type: 'group',
            children: [
              {
                type: 'CubeLeft',
                shape: {
                  api,
                  params,
                  x: location[0],
                  y: location[1],
                  xAxisPoint,
                  yBase,
                },
                style: {
                  fill: LinearGradientColor[params.seriesIndex].left,
                },
              },
              {
                type: 'CubeRight',
                shape: {
                  api,
                  x: location[0],
                  y: location[1],
                  xAxisPoint,
                  yBase,
                },
                style: {
                  fill: LinearGradientColor[params.seriesIndex].right,
                },
              },
              {
                type: 'CubeTop',
                shape: {
                  api,
                  yValue: api.value(1),
                  x: location[0],
                  y: location[1],
                  xAxisPoint,
                  yBase,
                },
                style: {
                  fill: LinearGradientColor[params.seriesIndex].top,
                },
              },
            ],
          }
        },
        data: y[j],
      }
    }),
  };