echarts柱状图 设置多个横坐标共用一个柱子

需求

展示一个柱状图,x轴为日期,y轴为百分比。要求每个y轴要用两个柱堆叠占满,且柱的宽度可跨多个横坐标。例:(1月1日-6月1日) 展示一个柱;(6月1日-9月1日) 展示一个柱,如下图

 实现

实现思路:x轴y轴展示都容易,y轴堆叠占满可以通过渲染两个柱堆叠来实现,跨横坐标的功能需要使用 自定义系列 去硬写柱的宽和高实现

  1.  x轴

    xAxis: {
        type: 'category',
    
        // 是否留白 图形两边和边界之间否留空
        boundaryGap: true,
    
        // x轴的刻度线和标签是否对齐
        axisTick: {
          alignWithLabel: true
        },
        data: [
          '01月01日',
          '02月01日',
          '03月01日',
          '04月01日',
          '05月01日',
          '06月01日',
          '07月01日',
          '08月01日',
          '09月01日',
          '10月01日',
          '11月01日',
          '12月01日'
        ]
      },
  2.  y轴

    yAxis: {
    
        // 最大100%
        max: 100,
    
        // 最小0%
        min: 0,
    
        // y轴分隔成多少份,
        splitNumber: 10,
    
        // y轴标签加单位
        axisLabel: {
          formatter: '{value} %'
        }
    },
  3. series

    series: [
       
       // 下面的柱
       {
            // 自定义类型
            type: 'custom',
    
            // 自定义的图形渲染逻辑
            // params 
            renderItem: function (params, api) {
                    
                // 通过值获取图形在图表里的像素坐标
                var start = api.coord([api.value(0), api.value(2)]);
                
                // 通过值获取图形在图表里的宽和高
                var size = api.size([api.value(0), api.value(2)]);
    
                // 因为x轴是均匀的12份,所以一份的宽度就是 All/12
                // params.coordSys.width 整个图型的宽度
                var width = params.coordSys.width / 12;
    
                // 输出
                return {
                    type: 'rect',
                    shape: {
    
                        // x轴上 柱的起始坐标
                        x: start[0],
    
                        // y轴上 柱的结束坐标
                        y: start[1],
    
                        // 柱的宽度
                        width: width * api.value(1),
    
                        // 柱的高度
                        height: size[1]
    
    
                        // 生成一个矩形需要知道xy的最大最小来确定范围
                        // xMax = x + width; xMin = x
                        // yMax = y; yMin = y - height
        
                    },
                    style: api.style()
                };
            },
    
            // 标题展示的位置
            label: {
                show: true,
                position: 'inside'
            },
    
            // 定义data里的维度名称
            dimensions: ['起始日期', '结束日期', 'name'],
    
            // 定义维度对应什么
            encode: {
                //  x轴使用data里的第一个维度数据
                x: 0,
    
                //  y轴使用data里的第三个维度数据
                y: 2,
    
                // 图例使用data里的第三个维度数据
                tooltip: 2,
    
                // 名称使用data里的第四个维度数据
                itemName: 3
            },
            data: [
    
                // '01月01日'    x轴的值
                // 5    当前图形跨越x轴坐标的个数,用于计算柱的宽度
                // 30    y轴的值
                // 'a'    名称
                ['01月01日', 5, 30, 'a'],
                ['06月01日', 3, 10, 'b'],
                ['09月01日', 3, 37, 'c']
            ].map((item, index) => {
                return {
                    value: item,
                    itemStyle: {
                        color: ['#66CCFF', '#ff6699', '#ccff99'][index]
                    }
                };
            });
        },
       
        // 上面的柱
        {
            type: 'custom',
            renderItem: function (params, api) {
                
                // 和上面的区别是 yMax现在是最大也就是100了 yMin = yMax- Height
                var start = api.coord([api.value(0), 100]);
                var size = api.size([api.value(0), 100 - api.value(2)]);
                var width = params.coordSys.width / 12;
                return {
                    type: 'rect',
                    shape: {
                        x: start[0],
                        y: start[1],
                        width: width * api.value(1),
                        height: size[1]
                    },
                    style: api.style()
                };
            },
            label: {
                show: true,
                position: 'inside',
                color: '#000'
            },
            dimensions: ['起始日期', '结束日期', 'name'],
            encode: {
                x: 0,
                y: 2,
                tooltip: [0, 1, 2],
                itemName: 3
            },
            data: [
                ['01月01日', 5, 30, 'a'],
                ['06月01日', 3, 10, 'b'],
                ['09月01日', 3, 37, 'c']
            ].map((item, index) => 
                return {
                    value: item,
                    itemStyle: {
                        color: ['#66CCFF', '#ff6699', '#ccff99'][index]
                    }
                };
            });
        }
    ]
  4. 完整代码

        其它的部分比较简单就不完善了

const data1 = [
  ['01月01日', 5, 30, 'a'],
  ['06月01日', 3, 10, 'b'],
  ['09月01日', 3, 37, 'c']
].map((item, index) => {
  return {
    value: item,
    itemStyle: {
      color: ['#66CCFF', '#ff6699', '#ccff99', '#bce9a6', '#8da2e4'][index]
    }
  };
});
const data2 = [
  ['01月01日', 5, 30, 'A'],
  ['06月01日', 3, 10, 'B'],
  ['09月01日', 3, 37, 'C']
].map((item, index) => {
  return {
    value: item,
    itemStyle: {
      color: ['#a4e0f7', '#ff9b9b', '#ffe68f', '#bce9a6', '#8da2e4'][index]
    }
  };
});
option = {
  title: {
    text: '百分比',
    left: 'center'
  },
  tooltip: {},
  xAxis: {
    type: 'category',
    boundaryGap: true,
    axisTick: {
      alignWithLabel: true
    },
    data: [
      '01月01日',
      '02月01日',
      '03月01日',
      '04月01日',
      '05月01日',
      '06月01日',
      '07月01日',
      '08月01日',
      '09月01日',
      '10月01日',
      '11月01日',
      '12月01日'
    ]
  },
  yAxis: {
    max: 100,
    min: 0,
    splitNumber: 20,
    axisLabel: {
      formatter: '{value} %'
    }
  },
  series: [
    {
      type: 'custom',
      renderItem: function (params, api) {
        var start = api.coord([api.value(0), api.value(2)]);
        var size = api.size([api.value(0), api.value(2)]);
        var width = params.coordSys.width / 12;
        return {
          type: 'rect',
          shape: {
            x: start[0],
            y: start[1],
            width: width * api.value(1),
            height: size[1]
          },
          style: api.style()
        };
      },
      label: {
        show: true,
        position: 'inside'
      },
      dimensions: ['起始日期', '结束日期', 'name'],
      encode: {
        x: 0,
        y: 2,
        tooltip: 2,
        itemName: 3
      },
      data: data1
    },
    {
      type: 'custom',
      renderItem: function (params, api) {
        var start = api.coord([api.value(0), 100]);
        var size = api.size([api.value(0), 100 - api.value(2)]);
        var width = params.coordSys.width / 12;
        return {
          type: 'rect',
          shape: {
            x: start[0],
            y: start[1],
            width: width * api.value(1),
            height: size[1]
          },
          style: api.style()
        };
      },
      label: {
        show: true,
        position: 'inside',
        color: '#000'
      },
      dimensions: ['起始日期', '结束日期', 'name'],
      encode: {
        x: 0,
        y: 2,
        tooltip: [0, 1, 2],
        itemName: 3
      },
      data: data2
    }
  ]
};

     

 参考:  

echarts自定义 - 利润分布直方图

自定义里 renderItem 的方法与参数

补充20230605

1. x轴的日期不为规则的如何显示(如【01-02,02-15,04-20】)

将x轴的data设置为365天[01-01,01-02 ··· 12-31],series的data设置为二维数组[[01-02,100],[02-15,140],[04-20,300]],这样就能找到对应的点

注:x轴的标签会重叠,因为300多项太多了,需要进行过滤:xAxis.axisLabel.interval = (index, value) => xData.includes(value),这样x轴就会只展示有数据的标签

2. x轴标签还是重叠了怎么办

几种办法

1. xAxis.axisLabel.interval:设置标签之间的间隔或者通过回调去设置

1. xAxis.axisLabel.rotate:可以设置标签的倾斜度数

2. xAxis.axisLabel.hideOverlap:true:5.2.0以上的版本可以通过设置这个属性去隐藏重叠的标签

3. 类目轴怎么设置两侧留白

添加额外数据:比如数据的范围是01/01~12/31,那么就可以往x轴的data就前后各加30天

有的人会问,01-01这种为什么不格式化成数字去设置两边的留白呢?

01-01 这种字符x轴对应的是类目轴(category),就是data的x值是多少,x轴就展示什么标签

0101 会变成数值轴(value),x轴标签会显示值附近的整数(值是0102,x轴的标签就是100、200)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 可以使用 echarts 的 dataset 组件来实现多个横坐标柱子合并。 首先,需要将数据按照不同的横坐标分组,并将每组数据转换为一个二维数组。例如,假设有三个横坐标 A、B、C,对应的数据分别为 [1, 2, 3]、[4, 5, 6]、[7, 8, 9],则可以转换为以下格式: ```javascript { dimensions: ['x', 'y'], source: [ ['A', 1], ['A', 2], ['A', 3], ['B', 4], ['B', 5], ['B', 6], ['C', 7], ['C', 8], ['C', 9] ] } ``` 然后,在 echarts 的 option 中配置 dataset 组件和 series 组件。其中,dataset 组件需要指定数据源,并配置 dimensions 和 source;series 组件需要使用 dataset 中的数据,并设置 seriesLayoutBy 属性为 'column',表示按列排列。 下面是一个简单的示例代码: ```javascript option = { dataset: { dimensions: ['x', 'y'], source: [ ['A', 1], ['A', 2], ['A', 3], ['B', 4], ['B', 5], ['B', 6], ['C', 7], ['C', 8], ['C', 9] ] }, series: [{ type: 'bar', seriesLayoutBy: 'column', encode: { x: 'x', y: 'y' } }] }; ``` 这样就可以实现多个横坐标柱子合并了。需要注意的是,如果多组数据之间的横坐标不一致,需要在 dataset 中使用 unionDimensions 属性来合并相同的维度。例如,如果有两组数据分别为 [A, B, C] 和 [B, C, D],则可以配置 unionDimensions: ['x'] 来合并横坐标为 B 和 C 的数据。 ### 回答2: 要实现echarts柱状图多个横坐标柱子合并,可以通过设置柱状图的宽度和坐标轴的配置来实现。 首先,设置柱状图的宽度。可以通过设置series中的itemStyle属性,将barWidth属性设置一个较小的数值来实现。该数值决定了每根柱子的宽度,可以根据实际需求进行调整。 其次,调整坐标轴的配置。对于多个横坐标柱子合并,可以通过设置xAxis的type属性为"category",将多个横坐标作为一个数组赋值给xAxis的data属性。然后,设置xAxis的axisLabel属性中的interval属性来控制横坐标显示的间隔,以适应多个横坐标的显示需求。 例如,假设有两个横坐标:"A"和"B",可以将它们作为数组["A", "B"]赋值给xAxis的data属性,然后将xAxis的axisLabel的interval属性设置为0,即每个横坐标都显示。 最后,将以上配置应用到echarts的实例中,即可实现多个横坐标柱子合并。 ### 回答3: 在Echarts柱状图中实现多个横坐标柱子合并,可以通过使用Echarts中的堆叠柱状图(stack)属性来实现。 首先,需要在Echarts的配置中设置xAxis参数,其中的type属性设置为"category"表示横坐标类型为分类类型,而不是连续类型。 接下来,设置series参数,其中的type属性设置为"bar"表示图表类型为柱状图,而不是其他类型,同时设置stack属性为"合并名称",表示需要将此series下的柱子合并为一组。例如: ``` xAxis: { type: 'category', data: ['横坐标1', '横坐标2', '横坐标3'] }, series: [ { name: '柱子1', type: 'bar', stack: '合并名称', data: [100, 200, 300] }, { name: '柱子2', type: 'bar', stack: '合并名称', data: [150, 250, 350] } ] ``` 上述代码中,横坐标有三个分类,即"横坐标1"、"横坐标2"、"横坐标3"。设置了两个series,它们的stack属性均设置为"合并名称",表示需要将这两个series下的柱子进行合并。 这样配置后,在图表中就会显示出两个柱子组,并且横坐标相同柱子会进行合并,形成一组数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值