绘制混合图表

在 G2 中,混合图表的绘制非常简单,仍然可以通过组合的方式解决,只需在当前 chart 上声明多个 geometry 即可,当然也可以使用多 View 方案。对于异构数据(即多份数据源),可以使用多 View 绘制。下面就通过一个例子向大家详细介绍绘制方法。

带均值线的区间面积图

image.png

上图由面积图 + 折线图 + 点图组合而成,其中面积区域可视化的是这段时间的温度范围,即每日的最高和最低气温,而折线图表示的是每日的平均温度变化,该图表的数据结构如下,其中 time 字段代表的是日期,以时间戳的格式存储, rangeTemp 代表每日温度区间, averageTemp 代表该日的平均温度。

  1. [
  2. { time: 1246406400000, rangeTemp: [14.3, 27.7], averageTemp: 21.5 },
  3. { time: 1246492800000, rangeTemp: [14.5, 27.8], averageTemp: 22.1 },
  4. { time: 1246579200000, rangeTemp: [15.5, 29.6], averageTemp: 23 },
  5. { time: 1246665600000, rangeTemp: [16.7, 30.7], averageTemp: 23.8 },
  6. { time: 1246752000000, rangeTemp: [16.5, 25.0], averageTemp: 21.4 },
  7. { time: 1246838400000, rangeTemp: [17.8, 25.7], averageTemp: 21.3 },
  8. { time: 1246924800000, rangeTemp: [13.5, 24.8], averageTemp: 18.3 },
  9. { time: 1247011200000, rangeTemp: [10.5, 21.4], averageTemp: 15.4 },
  10. { time: 1247097600000, rangeTemp: [9.2, 23.8], averageTemp: 16.4 },
  11. { time: 1247184000000, rangeTemp: [11.6, 21.8], averageTemp: 17.7 },
  12. { time: 1247270400000, rangeTemp: [10.7, 23.7], averageTemp: 17.5 },
  13. { time: 1247356800000, rangeTemp: [11.0, 23.3], averageTemp: 17.6 },
  14. { time: 1247443200000, rangeTemp: [11.6, 23.7], averageTemp: 17.7 },
  15. { time: 1247529600000, rangeTemp: [11.8, 20.7], averageTemp: 16.8 },
  16. { time: 1247616000000, rangeTemp: [12.6, 22.4], averageTemp: 17.7 },
  17. { time: 1247702400000, rangeTemp: [13.6, 19.6], averageTemp: 16.3 },
  18. { time: 1247788800000, rangeTemp: [11.4, 22.6], averageTemp: 17.8 },
  19. { time: 1247875200000, rangeTemp: [13.2, 25.0], averageTemp: 18.1 },
  20. { time: 1247961600000, rangeTemp: [14.2, 21.6], averageTemp: 17.2 },
  21. { time: 1248048000000, rangeTemp: [13.1, 17.1], averageTemp: 14.4 },
  22. { time: 1248134400000, rangeTemp: [12.2, 15.5], averageTemp: 13.7 },
  23. { time: 1248220800000, rangeTemp: [12.0, 20.8], averageTemp: 15.7 },
  24. { time: 1248307200000, rangeTemp: [12.0, 17.1], averageTemp: 14.6 },
  25. { time: 1248393600000, rangeTemp: [12.7, 18.3], averageTemp: 15.3 },
  26. { time: 1248480000000, rangeTemp: [12.4, 19.4], averageTemp: 15.3 },
  27. { time: 1248566400000, rangeTemp: [12.6, 19.9], averageTemp: 15.8 },
  28. { time: 1248652800000, rangeTemp: [11.9, 20.2], averageTemp: 15.2 },
  29. { time: 1248739200000, rangeTemp: [11.0, 19.3], averageTemp: 14.8 },
  30. { time: 1248825600000, rangeTemp: [10.8, 17.8], averageTemp: 14.4 },
  31. { time: 1248912000000, rangeTemp: [11.8, 18.5], averageTemp: 15 },
  32. { time: 1248998400000, rangeTemp: [10.8, 16.1], averageTemp: 13.6 },
  33. ];

下面我们开始使用以下两种方式来绘制这张混合图表。

使用 Geometry 组合方式

声明图形语法

首先我们需要确定几何标记以及图形属性映射规则:

  • 从图形特征来看,该图表是由『面积图』 + 『折线图』 + 『点图』三种基础图表组合而成的,所以需要使用
  • area, 对应面积图
  • line, 对应折线图
  • point,对应点图
  • 图形属性映射规则:
  • 对于面积图, time 以及 rangeTemp 字段分别确定图形位置(x 和 y)
  • 对应折线图和点图,time 以及 averageTemp 字段分别确定图形位置(x 和 y) 确定好映射规则后,就可以开始图表的绘制了:
  1. const chart = new Chart({
  2. container: 'mountNode',
  3. autoFit: false,
  4. width: 400,
  5. height: 300,
  6. });
  7. chart.data(data);
  8. chart.area().position('time*rangeTemp');chart.line().position('time*averageTemp');chart .point() .position('time*averageTemp') .shape('circle') .style({ stroke: '#fff', lineWidth: 1, fillOpacity: 1, });chart.render();

image.png

外观调整

但是从绘制结果看,并不理想,因此我们还需要做一些外观调整:

调整 x 轴的文本的显示格式

x 轴对应 time 字段,代表日期,在原始数据中是以时间戳的格式存储的,因为 G2 内部默认会将其转换为数值型度量(linear),但是我们实际希望她能以日期:'MM-DD' 的格式展示,所以我们使用 chart.scale() 接口对 time 字段进行了如下定义:

  1. chart.scale({
  2. time: {
  3. type: 'time', // 声明为 time 类型
  4. mask: 'MM-DD', // 格式化日期
  5. nice: true,
  6. },
  7. });

image.png

同步双 Y 轴数值范围

在 G2 中,实现多 Y 轴的绘制非常简单,用户完全不需要做任何配置。只要做到各个 geom 的 X 轴属性相同, Y 轴属性不同,G2 就会为您自动生成。正如该图一样,因为折线图和面积图的 y 轴映射字段不同,就会自动生成双 Y 轴(按照声明顺序从左到右依次生成),但是有一个问题, 就是因为两个字段的数值范围不同,导致两条 Y 轴的数值范围也不同,然后这两个字段的数据又具有关联性,所以我们需要对数据进行同步,因此我们使用 **chart.scale()**<code>接口为</code>rangeTemp<code>和</code>averageTemp<code>配置</code>sync 属性:

  1. chart.scale({
  2. averageTemp: { sync: 'value', }, rangeTemp: { sync: 'value', }, time: {
  3. type: 'time',
  4. mask: 'MM-DD',
  5. nice: true,
  6. },
  7. });

image.png

隐藏一条坐标轴

因为两个 Y 轴表示的是同样的数值范围,所以我们在这里只需要展示一条即可,因此我们选择将 averageTemp 字段对应的 Y 轴隐藏:

  1. chart.axis('averageTemp', false);

image.png

配置 tooltip

为了达到图表阅读的高效性,我们对 tooltip 进行如下配置:

  1. chart.tooltip({
  2. shared: true, // 合并数据
  3. showCrosshairs: true, // 展示辅助线
  4. });

多 View 绘制方式

下面我们再使用多 View 的方式绘制上图。

拆分 View

我们将面积图绘制在一个子 View 中,折线图和点图绘制在另一个子 View 中,显然这两个子 View 的绘图范围是相同的。

  1. const view1 = chart.createView();
  2. view1.data(data);
  3. view1.area().position('time*rangeTemp');
  4. const view2 = chart.createView();
  5. view2.data(data);
  6. view2.line().position('time*averageTemp');
  7. view2
  8. .point()
  9. .position('time*averageTemp')
  10. .shape('circle')
  11. .style({
  12. stroke: '#fff',
  13. lineWidth: 1,
  14. fillOpacity: 1,
  15. });

image.png

外观调整

使用多 View 的绘图方式,同样会涉及到上述问题,所以我们同样可以根据上述的配置,对图表进行调整。因为子 View 会继承父 View 在 scale, coordinate, tooltip, legend 以及 animate 上的配置,所以我们可以直接在 chart 上进行配置:

  1. chart.scale({
  2. averageTemp: {
  3. sync: 'value',
  4. },
  5. rangeTemp: {
  6. sync: 'value',
  7. },
  8. time: {
  9. type: 'time',
  10. mask: 'MM-DD',
  11. nice: true,
  12. },
  13. });

image.png