组织者:前端早早聊
分享人:新茗,蚂蚁金服
关于G2Plot
G2Plot的诞生与定位
为什么有了G2(常规统计图表可视化引擎),还会有G2Plot呢?
G2使用图形语法绘图,有一定上手成本,非开箱即用。所以需要一个简单、易用且具备一定扩展能力的图表库——G2Plot。
G2Plot有下述优点:
- 开箱即用,默认具备良好视觉和交互体验
- 易于配置,配置化API且使用认知统一
- 开发可扩展,最好是能够直接发挥图形语法的想象空间
定位:基于G2图形语法理论的开箱即用统计图表库。
G2Plot做什么?不做什么?
会做:
- 基于图形语法封装业务图表
- 遵循可视化设计规范进行针对性优化
- 配置式API降低成本
不会做(G2做)
- 图表繁琐的实现细节
- 布局、交互、动画、事件机制
技术架构
核心思路
G2命令式API用配置式API替代
// G2
import * as G2 from '@antv/g2';
const chart = new G2.Chart({
container: 'container'
});
chart.data(data);
chart.line().position('year*value');
chart.color('category');
chart.axis('year', {});
chart.axis('value', {});
chart.render();
=> 适配器 =>
import { Line } from '@antv/g2plot';
const plot = new Line("container", {
data,
xField: "year",
yField: "value",
seriesField: "category",
isStack: true,
xAxis: {},
yAxis: {},
});
plot.render();
适配器设计
适配器如何一图一做,每增加一种新图表,就需要增加一份绘图逻辑(扩展成本)。一旦需求发出变化或者底层依赖API变化,就很难维护了。
流水线组合的适配器
// 折线图适配器
export function adaptor(params: Params<LineOptions>) {
return flow(
theme,
// 折线图几何图形
geometry,
meta,
axis,
legend,
tooltip,
)(params);
}
这里借助了lodash的flow函数思想,按顺序调用数组中的方法,每个函数执行的结果作为下个函数的入参。
每个图表的适配器可以拆分为若干个适配器,每个适配器执行之后,还是新的适配器。可以进行自由的组合,前置依赖关系可以通过顺序保证,彼此之间没有很耦合的依赖。
适配器进行流水线化之后,可以将原来混杂的绘图逻辑清晰地划分为若干步骤。
模块内聚,减少耦合,提高复用性。
那么模块是如何拆分的呢?
模块划分
图表基本功能:几何图形+坐标轴+图例+悬浮信息+数据标签+图形标注等。
图表增强功能:交互、动画、状态、主题等。、
内置的适配器模块划分和图表的功能基本是一致的
复用性
有了适配器以后,如果绘制折线图,替换为line geometry适配器,柱状图替换为interval geometry适配器。其余适配器,比如axis、legend不用改变。
维护性
降低复杂性的基本方法,就是把复杂性隔离。”如果能把复杂性隔离在一个模块,不与其他模块互动,就达到了消除复杂性的目的。“
软件架构的复杂度:
- 认知负荷
- 协同成本
G2Plot考虑了这两点
- 逻辑符合思维习惯,与物理世界的概念符合。如:G2Plot按照图表组成和功能进行模块划分。
- 模块相对独立,边界清晰,通过原子化的方式进行组合。由于架构的约束,G2Plot 开发者的改动只会影响自己的那部分模块,边界较为清晰,代码也更容易维护,且每个模块有对应的单元测试。
扩展性
支持定义适配器
API设计思考
schema 结构设计
认知统一
- 不同图表同一类型的配置命名相同
- G2、G2Plot 相同概念保持一致的配置
- 贴合适配器模块
配置简单
- G2 提供的灵活性与使用成本的权衡
- G2Plot 进行一定的封装,提供更简单的配置化方式
BI / low-code 友好
- 面向 BI 低代码搭建的友好
如何选型 G2、G2Plot、AntD-Charts
react 技术栈且图表自定义诉求不强:AntD-Charts
定制诉求不强,G2Plot 内置图表基本可满足:G2Plot
具备丰富交互、需要定制的个性化信息图表:G2Plot自定义扩展图表adaptor模式 或者 G2 / G
从 G、G2、G2Plot 再到 Ant Design Charts,我们只有一个目的:降低开发入⻔⻔槛,如何选择取决于你对各图表库的理解程度。