一、前言

几周前,产品突然过来跟我说,甲方要求把两个柱子的距离挨得近一点,(我心想 这有啥难的 这不白给的任务 给我写日报的嘛)

但当产品给我打开页面,指了指那几根柱子时,我竟一时间大脑萎缩 反应不过来。

双坐标1.png我:啊?你是想让这些柱子,两两靠近在一起嘛?

产品:对啊,调整下柱子间距应该很快吧。

我:&*&%%……^#@!

二、echarts双坐标轴展示

  • 经过不断的GPT+百度的探索,也是找到了变相可以解决的操作,就是通过设置grid以及添加一个X轴、Y轴,和一份描述数据,使其能够包裹住这两两柱子,形成一种包含关系:

  • 双坐标2.png

三、实现方法

  1. 新增一个grid对象,使得底部镶嵌合适。

      grid: [
       //咱们实际展示的 grid1
        {
          top: '10%',
          left: '20',
          right: '20',
          bottom: '12%',
          containLabel: true
        },
       // 底部的grid2
        {
          left: '50',
          right: '20',
          height: '10%',
          bottom: '5%',
          tooltip: {
            show: false
          }
        }
      ],

    双坐标3.png 双坐标2.png

  2. 定义两个X轴,一个用来展示柱状图的数据,一个用来作为我们父级的坐标轴,用以展示(xx部门、yy部门)。

    • 注意gridIndex: 1,第二个父级x轴使用第二个grid用以绘图网格

      xAxis: [
        {
          type: 'category',
          data: ['昨日人数','今日人数','昨日人数','今日人数','昨日人数','今日人数'],
          axisPointer: {
            type: 'shadow'
          }
        },
        // 记得将坐标轴文本、坐标刻度线等 不展示
        {
          type: 'category',
          gridIndex: 1,
          axisLine: {
            show: false
          },
          axisTick: {
            show: false
          },
          axisLabel: {
            show: false
          }
        }
      ],
  3. 定义两个y轴,一个用来展示柱状图的数据,一个用来作为我们父级的坐标轴(记得隐藏坐标轴刻度线等)

    • 注意gridIndex: 1,第二个父级y轴使用第二个grid用以绘图网格

      yAxis: [
        {
          type: 'value',
          name: '人数',
          barWidth: 40,
          min: 0,
          max: 250,
          interval: 50
        },
        {
          type: 'value',
          gridIndex: 1,  // 使用第二个grid
          axisPointer: {
            // 注意这里是 axisPointer,不是 axisPointer2
            show: false // 第二个 Y 轴的指示器隐藏
          },
          axisLabel: {
            show: false
          },
          axisLine: {
            show: false
          },
          splitLine: {
            show: false
          },
          axisTick: {
            show: false
          }
        }
      ],
  4. 处理当前后端传回来的数据,定义seriesData。

    // 模拟 后端返回的数据
    let apiData = [
      {
        name: 'xx部门',
        last1: 2.0, //昨日承包商人数
        last2: 2.6, //昨日正式员工人数
        now1: 4.9, // 今日承包商人数
        now2: 5.9 // 今日正式员工人数
      },
      {
        name: 'yy部门',
        last1: 7.0, //昨日承包商人数
        last2: 9.0, // 昨日正式员工人数
        now1: 23.2, //今日人数
        now2: 26.4 // 今日人数
      },
      {
        name: 'zz部门',
        last1: 25.6, //昨日人数
        last2: 28.0, // 昨日人数
        now1: 76.2, //今日人数
        now2: 70.4 // 今日人数
      }....
    ];
    
      series: [
        {
          name: '承包商',
          type: 'bar',
          stack: 'kk',
          barWidth: 50,
          xAxisIndex: 0,
          yAxisIndex: 0,
          data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7] // 通过遍历处理生成的data
        },
        {
          name: '员工',
          type: 'bar',
          stack: 'kk',
          xAxisIndex: 0,
          yAxisIndex: 0,
          data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7] // 通过遍历处理生成的data
        },
      ],
  5. 定义seriesData,以及处理echarts最下方的第二坐标轴的数据(注意x轴y轴 的对于关系)

    series: [
      ...... //上方series(承包商 员工的数据)
        {
          data: [  // 第二x坐标轴的数据,通过对apiData的遍历处理得到的数据
            {
              name: 'xx部门',
              value: 1
            },
            {
              name: 'yy部门',
              value: 1
            },
            {
              name: 'zz部门',
              value: 1
            }
          ],
          animation: false,   //动画消失
          label: {
            show: true,
            position: 'inside',
            formatter: '{b}',  //展示数据名
            color: '#ccc'
          },
          type: 'bar',
          barGap: 0,
          barWidth: '100%',
          itemStyle: {
            normal: {
              color: 'rgba(255,255,255,0)',
              borderColor: '#ccc'
            }
          },
          labelLine: {
            show: false
          },
          xAxisIndex: 1,  //对应第二个x轴
          yAxisIndex: 1  //对应第二个y轴
        }
      ]

  1. 最终呈现效果

    双坐标2.png

四、完整代码

let apiData = [
  {
    name: 'xx部门',
    last1: 2.0, //昨日承包商人数
    last2: 2.6, //昨日正式员工人数
    now1: 4.9, // 今日承包商人数
    now2: 5.9 // 今日正式员工人数
  },
  {
    name: 'yy部门',
    last1: 7.0, //昨日承包商人数
    last2: 9.0, // 昨日正式员工人数
    now1: 23.2, //今日人数
    now2: 26.4 // 今日人数
  },
  {
    name: 'zz部门',
    last1: 25.6, //昨日人数
    last2: 28.0, // 昨日人数
    now1: 76.2, //今日人数
    now2: 70.4 // 今日人数
  }
];

option = {
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      type: 'cross',
      crossStyle: {
        color: '#999'
      }
    }
  },
  grid: [
    {
      top: '10%',
      left: '20',
      right: '20',
      bottom: '12%',
      containLabel: true
    },
    {
      left: '50',
      right: '20',
      height: '10%',
      bottom: '5%',
      tooltip: {
        show: false
      }
    }
  ],
  xAxis: [
    {
      type: 'category',
      data: [
        '昨日人数',
        '今日人数',
        '昨日人数',
        '今日人数',
        '昨日人数',
        '今日人数'
      ],
      axisPointer: {
        type: 'shadow'
      }
    },
    {
      type: 'category',
      gridIndex: 1,
      axisLine: {
        show: false
      },
      axisTick: {
        show: false
      },
      axisLabel: {
        show: false
      }
      // zlevel: 1
    }
  ],
  yAxis: [
    {
      type: 'value',
      name: '人数',
      barWidth: 40,
      min: 0,
      max: 250,
      interval: 50
    },
    {
      type: 'value',
      gridIndex: 1,
      axisPointer: {
        // 注意这里是 axisPointer,不是 axisPointer2
        show: false // 第二个 Y 轴的指示器隐藏
      },
      axisLabel: {
        show: false
      },
      axisLine: {
        show: false
      },
      splitLine: {
        show: false
      },
      axisTick: {
        show: false
      }
    }
  ],
  series: [
    {
      name: '承包商',
      type: 'bar',
      stack: 'kk',
      barWidth: 50,
      xAxisIndex: 0,
      yAxisIndex: 0,
      data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7]
    },
    {
      name: '员工',
      type: 'bar',
      stack: 'kk',
      xAxisIndex: 0,
      yAxisIndex: 0,
      data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7]
    },
    {
      data: [
        {
          name: 'xx部门',
          value: 1
        },
        {
          name: 'yy部门',
          value: 1
        },
        {
          name: 'zz部门',
          value: 1
        }
      ],
      label: {
        show: true,
        position: 'inside',
        formatter: '{b}',
        color: '#ccc'
      },
      type: 'bar',
      barGap: 0,
      barWidth: '100%',
      itemStyle: {
        normal: {
          color: 'rgba(255,255,255,0)',
          borderColor: '#ccc'
        }
      },
      labelLine: {
        show: false
      },
      xAxisIndex: 1,
      yAxisIndex: 1
    }
  ]
};