echarts dimensions 多维数据映射

274 阅读2分钟

这周在做可视化图表的时候,遇到一些复杂的需求,最后效果如下图所示: 折柱混合图

image.png

难点:后端接口的返回值数据结构很难符合前端开发所需的数据结构,因此面对 echarts 这类固定输入得到固定输出的库时,我们需要做一遍数据处理。

官方示例写法

那么首先我们需要清楚,在 echarts 中想要完成折柱混合图需要什么数据结构? 官方折柱混合图示例

官方的示例中,重点代码在这里:不难看出,官方是将 x 轴数据和 y 轴数据分开了,然后数据源按照index一一对应。这会加大我们的数据处理难度,因为后端返回的数据通常是Object[]

// 这里仅保留重点代码
option = {
  
  xAxis: [
    {
      type: 'category',
      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
    }
  ],
  // ....
  series: [
    {
      name: 'Evaporation',
      type: 'bar',
      data: [
        2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3
      ]
    },
    {
      name: 'Precipitation',
      type: 'bar',
      data: [
        2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3
      ]
    },
    {
      name: 'Temperature',
      type: 'line',
      yAxisIndex: 1,
      data: [2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2]
    }
  ]
};

更简单的写法(?)

为了简化数据处理,我们可以用dimensions映射的方式来完成这个需求。重点代码如下:

const options = {
    dataset: [
        {
          source: data,  // [{a: 1, timestamp: xxx, name: '用于 tooltip 映射也是可以的哦'}, {...}]
          dimensions: ['timestamp', 'a', 'name'],
        },
        {
          source: lineData, // { key: 1, timestamp: xxx }[]
          dimensions: ['timestamp', 'key'],
        },
      ],
      series: [
        {
          type: 'line',
          name: '折线图名称',
          yAxisIndex: 1,
          datasetIndex: 1,
        },
        {
          name: '柱状图名称',
          type: 'bar',
          stack: 'a'  // 需要映射的 key,
          data: // 需要处理成 ['timestamp', 'a'] 的形式,就跟上面一样,
        },
        {
          name: '2 号柱状图名称',
          type: 'bar',
          stack: dimensionKey,
          barMaxWidth: 100,
          barWidth: '50%',
          data: // 需要,
        },
      ],
      tooltip: {
          formatter: (val) => {
              val.map((item) => {
                if (item.componentSubType === 'line') {
                  const yData = item?.data['key']
                  let xData = item?.data?.timestamp
                  console.log(item?.marker) // 圆点
                }
                if (item.componentSubType === 'bar') {
                  xData = item?.data[0]
                  const barYData = item?.data[1]
              })
              return `
                    <div>
                      ....
                    </div>
                  `
        },
      }

}

总结

在本次需求中,数据是从多个接口获取的:折线图的数据是一个接口,柱状图的数据是一个接口。

const lineData = [
    {
        timestamp: ...,
        y: ...
    },
    {...}
]

const barData = [
    {
        timestamp: ...,
        y: ....
    },
    {  ... }
]

如何将这样的两个数据水合在一起组成折柱混合图,用 dimension 是一个容易的办法