Echarts 横向渐变格子柱状图

2024-05-07

要实现的效果如图: 效果图

特点包括:

  1. 横向。
  2. 柱状图是由多个格子组成的,而不是一整条。
  3. 颜色渐变。
  4. 背景是暗色格子。

实现思路

  1. 横向。修改 xy 轴的 type 即可。
  2. 格子柱状图。通过 echarts 的 renderItem 实现自定义绘制格子。不了解 renderItem, 可以看最下面参考中的前两个链接。
  3. 通过 echarts.color.lift 实现格子的颜色渐变。文档在下面参考的第三条。
  4. 暗色格子也是通过 renderItem 实现。先在横向铺满暗色格子充当背景,再把有色格子覆盖到暗色格子上面。

代码

代码含详细注释, 可直接粘贴到官方示例中看效果。

option = {
  backgroundColor: "#000",
  tooltip: {
    trigger: "axis",
  },
  yAxis: {
    type: "category",
    data: ["y1", "y2", "y3"],
    splitLine: {
      show: false,
    },
    axisLine: {
      show: true,
    },
    axisTick: {
      show: false,
    },
  },
  xAxis: {
    show: false,
    type: "value",
  },
  grid: {
    top: 50,
    left: 50,
  },

  series: [
    {
      data: [10, 20, 30],
      label: {
        show: true,
      },
      type: "custom",
      renderItem: function (params, api) {
        // api.value(0) 数值
        // api.value(1) 类别
        // 当前数值的坐标
        const valueCoord = api.coord([api.value(0), api.value(1)]);
        // 数值为0时的坐标
        const initialCoord = api.coord([0, api.value(1)]);
        // 柱状图的长度 = 当前数值的x坐标 - 数值为0时的x坐标
        const barLength = valueCoord[0] - initialCoord[0];
        const gap = 4; // 格子间的间距
        const height = 15; // 格子的高度
        const width = 8; // 格子的宽度
        // 格子的长度 = 格子的宽度 + 一个间距
        // 格子的数量 ≈ 柱状图的长度 / 单个格子的长度
        const barNum = Math.round(barLength / (width + gap));

        const itemStyle = api.style();

        const rects = Array.from({ length: barNum }, (_, index) => {
          // 第 index 个格子的x坐标 = 数值为0时的坐标 + 前面所有格子的长度和
          const rectX = initialCoord[0] + (width + gap) * index;
          return {
            type: "rect",
            enterFrom: {
              scaleX: 0.1,
              scaleY: 0.1,
              style: { opacity: 0 },
            },
            shape: {
              // x,y 是格子左上角的坐标
              y: valueCoord[1] - height / 2,
              x: rectX,
              width,
              height,
            },
            style: {
              fill: echarts.color.lift(
                itemStyle.fill,
                1 - rectX / api.getWidth()
              ),
            },
          };
        });

        // 预留 60px,在柱状图右边显示数值
        const textLength = 60;
        const bgbarNum = Math.round(
          (api.getWidth() - initialCoord[0] - textLength) / (width + gap)
        );

        const bgRects = Array.from({ length: bgbarNum }, (_, index) => {
          return {
            type: "rect",
            // enterFrom: {
            //   scaleX: 0.1,
            //   scaleY: 0.1,
            //   style: { opacity: 0 },
            // },
            shape: {
              y: valueCoord[1] - height / 2,
              x: initialCoord[0] + (width + gap) * index,
              width,
              height,
            },
            style: {
              fill: "#2A4963",
            },
          };
        });

        const text = {
          type: "text",
          style: {
            text: api.value(0),
            // 6是文字的左padding
            x: api.getWidth() - textLength + 6,
            y: valueCoord[1] - height / 2 + 2,
            fill: "#93BEE0",
          },
        };
        return {
          type: "group",
          x: 0,
          y: 0,
          children: [...bgRects, ...rects, text],
        };
      },
      itemStyle: {
        color: "#FF7348",
      },
    },
  ],
};

参考: