echarts 实现不等分双x轴滚动

335 阅读2分钟

双x轴不等分情况实现思路:

  1. 一个网格为常规图,常规x轴作为子级;
  2. 另一个网格绘制柱状图,每根柱子就是一个父级,设置柱子的宽度(子级数占总数的百分比)即可。

代码:

const baseData = [
  {
    value: '贵阳市',
    children: [
      { value: '花溪区', num: 1, count: 12 },
      { value: '南明区', num: 15, count: 23 },
      { value: '观山湖区', num: 18, count: 42 }
    ],
    regionColor: '#F4BBB8'
  },
  {
    value: '六盘水市',
    children: [
      { value: '钟山区', num: 25, count: 35 },
      { value: '六枝特区', num: 23, count: 32 }
    ],
    regionColor: '#FFD1AF'
  },
  {
    value: '遵义市',
    children: [
      { value: '红花岗区', num: 32, count: 52 },
      { value: '汇川区', num: 33, count: 42 },
      { value: '遵义县', num: 36, count: 62 }
    ],
    regionColor: '#F3EFA3'
  },
  {
    value: '安顺市',
    children: [
      { value: '西秀区', num: 57, count: 52 },
      { value: '平坝县', num: 72, count: 62 }
    ],
    regionColor: '#D8D4EC'
  },
  {
    value: '铜仁市',
    children: [{ value: '玉屏县', num: 45, count: 42 }],
    regionColor: '#B1CEF8'
  }
];
const dLength = baseData
  .map((item) => item.children.length)
  .reduce((n, m) => n + m); // x轴数据总长度,用于计算父级x轴的宽度
let xData = [];
let yData1 = [];
let yData2 = [];
let series = [
  {
    name: '销量',
    data: yData1,
    type: 'line',
    label: {
      show: true,
      position: 'top',
      textStyle: {
        color: '#555'
      }
    },
    xAxisIndex: 0,
    yAxisIndex: 0,
  },
  {
    name: '库存',
    data: yData2,
    type: 'line',
    label: {
      show: true,
      position: 'top',
      textStyle: {
        color: '#555'
      }
    },
    xAxisIndex: 0,
    yAxisIndex: 0
  }
];
// 不同等份分区域
let baseObj = {
  data: [
    {
      name: '',
      value: 1
    }
  ],
  label: {
    show: true,
    position: 'inside',
    formatter: '{b}',
    offset: [0, 2],
    textStyle: {
      color: '#666'
    }
  },
  type: 'bar',
  barGap: 0,
  barWidth: '',
  itemStyle: {
    color: '',
    opacity: 0.8
  },
  animationEasing: 'bounceOut',
  xAxisIndex: 1,
  yAxisIndex: 1
};
baseData.forEach((item, index) => {
  let pObj = JSON.parse(JSON.stringify(baseObj));
  pObj.data[0].name = item.value;
  pObj.barWidth = (item.children.length / dLength) * 100 + '%';
  pObj.itemStyle.color = item.regionColor;
  series.push(pObj);
  item.children.forEach((cItem) => {
    xData.push({
      value: cItem.value,
      pName: item.value,
      regionColor: item.regionColor
    });
    yData1.push(cItem.num);
    yData2.push(cItem.count);
  });
});

myChart.setOption({
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      type: 'shadow'
    },
    formatter(params) {
      let str = '';
      baseData.forEach((item, index) => {
        item.children.forEach((cItem) => {
          if (cItem.value == params[0].name) {
            str = item.value + '<br/>' + params[0].name + '<br/>';
          }
        });
      });
      for (let item of params) {
        //设置浮层图形的样式跟随图中展示的颜色
        str +=
          "<span style='display:inline-block;width:10px;height:10px;margin-right:5px;border-radius:10px;background-color:" +
          item.color +
          ";'></span>" +
          item.seriesName +
          ' : ' +
          item.value+'<br/>';
      }
      return str;
    }
  },
  legend: { data: ['销量', '库存'] },
  grid: [
    {
      top: 100,
      bottom: 100
    },
    {
      height: 20,
      bottom: 100,
      tooltip: { show: false }
    }
  ],
  dataZoom: {
    type: 'slider'
  },
  xAxis: [
    {
      type: 'category',
      data: xData,
      gridIndex: 0,
      axisLabel: {
        color: '#333'
      },
      axisLine: {
        lineStyle: {
          color: '#e7e7e7'
        }
      },
      axisTick: {
        lineStyle: {
          color: '#e7e7e7'
        }
      },
      zlevel: 2
    },
    {
      type: 'category',
      gridIndex: 1,
      axisLine: { show: false },
      axisLabel: { show: false },
      axisTick: { show: false },
      zlevel: 1
    }
  ],
  yAxis: [
    {
      type: 'value',
      gridIndex: 0,
      axisLabel: {
        color: '#333'
      },
      splitLine: {
        lineStyle: {
          type: 'dashed'
        }
      },
      axisLine: {
        lineStyle: {
          color: '#ccc'
        }
      },
      axisTick: {
        lineStyle: {
          color: '#ccc'
        }
      }
    },
    {
      type: 'value',
      gridIndex: 1,
      axisLabel: { show: false },
      axisLine: { show: false },
      splitLine: { show: false },
      axisTick: { show: false }
    }
  ],
  series
});

// dataZoom缩放事件
myChart.on('dataZoom', (params) => {
  const dataZoom = myChart.getModel().option.dataZoom[0];
  const { startValue, endValue } = dataZoom;
  let curXdata = xData.slice(startValue, endValue + 1); // 缩放后的子级
  let curPdata = [...new Set(curXdata.map((item) => item.pName))]; // 取出父级去重
  series.length = 2; // 默认初始值
  curPdata.forEach((item, index) => {
    let length = 0;
    let regionColor = '';
    curXdata.forEach((cItem) => {
      if (cItem.pName === item) {
        length++;
        regionColor = cItem.regionColor;
      }
    });
    let pObj = JSON.parse(JSON.stringify(baseObj));
    pObj.data[0].name = item;
    pObj.barWidth = (length / curXdata.length) * 100 + '%';
    pObj.itemStyle.color = regionColor;
    series.push(pObj);
  });
  myChart.setOption(
    {
      series
    },
    {
      replaceMerge: 'series' // 替换合并series,默认普通合并
    }
  );
});


最终效果:

企业微信截图_16914789576104.png

line-smooth (1).png