开眼界!阿里用这样的组件开发大屏(二)

28,196 阅读5分钟

前文再续,书接上回:开眼界!阿里用这样的组件开发大屏(一)

Hi~ 我是前端学徒业枫,今天继续向大家分享可视化系列文章,介绍我们的前端开源图表库📈 CloudCharts(Github 欢迎试用&Issue&PR) 如何基于 G2 封装,解决其在大规模使用场景中遇到的问题,通过少量配置项即可绘制图表,服务内部近两百个产品和许多对外云产品。感兴趣的同学可以来官网在线体验:传送门

本期是系列第二篇,着重解答第三个问题:如何做到开箱即用,降低使用门槛?

为什么要做开箱即用?

为什么要做包装呢,直接用 G2 不是挺好的吗?

蚂蚁AntV G2 是一套面向常规统计图表,以数据驱动的高交互可视化图形语法,具有高度的易用性和扩展性。

图形语法

G2 的功能十分强大,但初学者从零开始学习图形语法,理解“视觉通道”、“数据映射”等专业可视化概念成本太高。直接使用G2很难支撑业务快速发展,还有让设计师们头秃的视觉对接成本,所以我们决定做开箱即用包装,降低大家的使用成本。

解法思路

1、配置化

既然图形语法难学,那就将其变为简单的配置项,通过向React组件传入配置即可完成图表。

2、功能增强

在实际使用中,G2 有一些常用的功能点缺失,不能上手即用。我们补充了常用的功能,降低使用的难度。

3、智能化

功能越多,配置越复杂,我们尝试用一些智能化配置,降低用户编写配置项的难度。

1、配置化

我们在组件库内部增加了“翻译器”函数,将用户传入的配置项转化为图形语法。翻译器会与G2的图形语法划分匹配。

我们先来看看 G2 图形语法的有哪些部分:

  • 顶层配置 ✅
  • 数据度量 Scale
  • 坐标系 Crood
  • 坐标轴 Axis ✅
  • 提示信息 Tooltip ✅
  • 图例 Legend ✅
  • 辅助标记 Guide ✅
  • 图形元素 Geom
  • 文本标签 Label ✅

其中打✅ 的部分在大多数图表中逻辑一致,可以抽象为统一的函数:

// 设置X轴
xAxis(this, chart, config);

// 设置Y轴
yAxis(this, chart, config);

// 设置图例
legend(this, chart, config);

// 设置tooltip
tooltip(this, chart, config);

// 设置辅助线,辅助背景区域
guide(this, chart, config);

例如在 xAxis 函数内,包装X轴相关的图形语法逻辑:

if (config.xAxis === false) {
  // 关闭 X 轴
  chart.axis('x', false);
  return;
}

const { alias, autoRotate, labelFormatter } = config.xAxis || {};
const xAxisConfig = {
  title: null,
  label: {
    autoRotate,
    formatter: labelFormatter,
  },
};

// 开启坐标轴标题
if (alias) {
  xAxisConfig.title = {
    position: 'center',
    offset: 38,
    textStyle: {
      rotate: 0,
    },
  };
}

chart.axis('x', xAxisConfig);

通过组合不同的“翻译器”函数,我们可以很方便的维护图表库,而用户只需要传入少量配置项即可完成图表绘制。

2、功能增强

我们还在翻译器的基础上增加了许多功能,同时修复一些Bug,让其使用起来更顺畅:

自动适配尺寸大小

G2默认只适配宽度,我们增加了对高度的适配,自动读取外层元素的高度。

自动响应数据更新

Props 传入的数据更新会自动刷新数据。

自动响应配置更新

Props 传入的配置项更新会自动更新图表。

图例折叠

图例项数量过多会挤占图表展示的空间,我们增加了图例折叠的功能,能收起过多的图例,保证展示效果。

地图等比例绘制

使用 G2 绘制地图时,图形会填满画布导致变形,我们通过一些算法保证图形能按“正确”的尺寸绘制。具体代码可以参考我在这个Issue antvis/G2#1364 中的回复。

CSS 缩放不影响 Tooltip 定位

我们在一些大屏中对图表应用CSS缩放,发现缩放后图表 Tooltip 的位置会错位。因为开发计划的原因无法PR修复,我们通过AOP的方式解决了这个问题。具体代码可以参考我在这个Issue antvis/G2#912 中的回复。

3、智能化

随着我们包装的功能越来越多,对应的配置也会越来越复杂,逐渐演变为一种新的“图形语法”。我们尝试加入一些智能化配置,让用户可以用简单的配置项代替复杂的配置,由图表内部针对当前上下文计算出合适的配置项:

自动计算时间格式

我们发现很多用户的时间格式设置不合理,于是增加这个功能。当用户不指定格式时,在内部读取数据中的时间跨度和时间间隔,计算得比较合适的时间格式。

间隔 \ 跨度大于一个月大于一天大于一小时大于一分钟
大于一个月YYYY-MM---
大于一天MM-DDMM-DD--
大于一小时MM-DD HH:mmMM-DD HH:mmHH:mm-
大于一分钟MM-DD HH:mmMM-DD HH:mmHH:mmHH:mm

图例过多自动折叠

前面提到了图例折叠功能,我们可以再进一步,让图表在图例占用一定高度时自动开启折叠展示功能。

// 自动适配图例折叠高度
const chartHeight = '图表高度';
const legendHeight = '图例总体高度';
const itemHeight = '图例单行高度';

// 行数最多占图表高度的三分之一,最小为2。
const collapseRow = Math.max(2, Math.round((chartHeight / itemHeight) / 3));

// 开启图例折叠
if (legendHeight > itemHeight * collapseRow) {...}

中场休息的分割线

经过上面的封装,图表库使用起来简单许多,大多数用户依靠文档和示例就能完成绘制。我们的目标基本达到啦~

由于篇幅有限,本期就到这里,我们下期再见!

📢 📢 大家对此有什么想法呢?欢迎在评论提出~


✏️ 下期预告

解答剩下两个问题,关注如何保证图表展示质量,并与上下游打通,形成完整的可视化操作链路。

4、如何收敛图表主题展现并快速切换主题?

5、如何低代码构建图表?

记得持续关注我们哦~

团队名片