1

首先看echarts的官网示例
image.png
可见第一幅图是具有离散点的箱图,第三幅是colorBy分组之后的箱图,拿到需求的时候,我寻思这不是都有吗,直接复用官网示例就完事了,但是实际效果不尽人意,因为echarts的同一个x值,如果对应的是三个series的箱子,是左右排列开的,如果对应的是三个series的散点,是在同一条竖线上排列,简单看一下效果
image.png
完全对应不上啊!
理解了为什么官网示例要么只有离散点,要么只有colorBy分组,而没有两者都兼顾的示例了。。。

撸起袖子开始找办法


首先,发现了散点图可以这样组织data进行分组,形式
[[x轴的值,对应的y的值],[x轴的值,对应的y的值],[x轴的值,对应的y的值],...]
image.png
这要是boxPlot也可以这样写,岂不是就解决解决了这个问题
大胆尝试一波,果然画不出来东西
image.png

但是也打开了思路,是不是可以用一个series放所有的箱图,通过itemStyle实现颜色的区分呢,(颜色分组要与series的color颜色分组一致)尝试一下,代码格式与呈现效果如下
image.png

那是不是就可以把刚刚的散点也加上,试一下
image.png
大概样子有了,但是x轴也不是x1对应两个颜色啊
那么再这么进行一下改造,对于x1对应的不同的颜色,在x轴拼上一个假的id,后面再基于假id之前的名字x1、x2之类的进行合并
image.png
options如下:

option = {
  xAxis: {
    type: 'category',
    data: ['x1_fakerId:1', 'x1_fakerId:2', 'x2_fakerId:1', 'x3_fakerId:1', 'x3_fakerId:2', 'x4_fakerId:1', 'x4_fakerId:2']
  },
  legend: {
    show: true,
    data: ['color1', 'color2']
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      data: [
        {
          value: [1.1, 1.2, 1.3, 1.4, 1.5],
          itemStyle: {
            borderColor: '#5470c6'
          }
        },
        {
          value: [3.1, 3.2, 3.3, 3.4, 3.5],
          itemStyle: {
            borderColor: '#91cc75'
          }
        },
        {
          value: [2.1, 2.2, 2.3, 2.4, 2.5],
          itemStyle: {
            borderColor: '#5470c6'
          }
        },
        {
          value: [5.1, 5.2, 5.3, 5.4, 5.5],
          itemStyle: {
            borderColor: '#5470c6'
          }
        },
        {
          value: [0.6, 2, 3, 4, 5],
          itemStyle: {
            borderColor: '#91cc75'
          }
        },
        {
          value: [2.4, 2.8, 3.5, 4.6, 4.9],
          itemStyle: {
            borderColor:' #5470c6'
          }
        },
        {
          value: [1.5, 2, 2.3, 3.6, 5.7],
          itemStyle: {
            borderColor: '#91cc75'
          }
        }
      ],
      type: 'boxplot',
      name: 'boxplot'
    },
    {
      data: [
        ['x1_fakerId:1', 1],
        ['x1_fakerId:1', 2],
        ['x2_fakerId:1', 3],
        ['x2_fakerId:1', 4],
        ['x3_fakerId:1', 8],
        ['x3_fakerId:1', 8.9],
        ['x3_fakerId:1', 8.4],
        ['x4_fakerId:1', 7.2]
      ],
      itemStyle: {
        color: '#5470c6'
      },
      type: 'scatter',
      name: 'color1'
    },
    {
      data: [
        ['x1_fakerId:2', 5.5],
        ['x3_fakerId:2', 6.7],
        ['x3_fakerId:2', 6],
        ['x3_fakerId:2', 7.6],
        ['x4_fakerId:2', 8.7],
        ['x4_fakerId:2', 5.8],
        ['x4_fakerId:2', 1.3]
      ],
      itemStyle: {
        color: '#91cc75'
      },
      type: 'scatter',
      name: 'color2'
    }
  ]
};

对于x轴的合并显示,参考之前的多层x轴的实现https://segmentfault.com/a/11...

最后,
对于lenged的变化,需要去监听legend的变化,去更新boxPlot对应的series

 myChart.on('legendselectchanged', (params: any) => {
        // console.log(params,'params');
        const currentOption = myChart.getOption();
        let currentSeries: KeyValue[] = currentOption.series as KeyValue[];

        if (currentSeries.length < 1) return;

        const currentSeriesBoxPlot = currentSeries[0];

        const newboxPloSeriestData: KeyValue[] = [];

        //依据个人组织的数据结构,自行处理对应的新的boxPlot的series
        points.map((item: KeyValue) => {
          const boxData = item.boxData;
          const ynName: string = Object.keys(boxData)[0];

          if (!isEmpty(params.selected))
            //如果选中了对应的yName,则处理填充对应的boxPlot的箱子的部分
            newboxPloSeriestData.push({
              value: params.selected[ynName] === true ? Object.values(boxData)[0] : [],
              itemStyle: {
                borderColor: ERCHARTSCOLORS[yn.indexOf(ynName) % 9],
              },
            });
        });

        const newSeriesBoxPlot = Object.assign({}, currentSeriesBoxPlot, { data: newboxPloSeriestData });

        currentSeries[0] = newSeriesBoxPlot;

        const newOption = Object.assign({}, currentOption, { series: currentSeries });

        myChart.setOption(newOption);
      });

最后的实现效果:
image.png

PS:该方案存在一个问题,因没有保存legend的选中状态,每次缩放之后,所有的series会重置为全部的箱图,待优化
PS2:Echarts社区还有另一种方案:https://www.makeapie.cn/echar...
利用pictorialBar类型画出的离散点,但是barGap的设置感觉会有坑,偶尔有离散点对不齐箱子中央的情况,若colorBy数量较少的时候,影响不大


2 声望2 粉丝