想了很久 G2 5.0 要做什么,怎么做,这里总一个汇总手稿。
G2 4.0
之前 G2 4.0 的发布内容。
- TypeScript(AntV 走出 ts 的第一步)
- Canvas & SVG(以前也有,反而升级 G 之后,Bug 很多,不推荐使用 SVG)
- 更新机制(更新并不能带来大幅度的性能提升)
- 组件体系升级( 增加 slider、scrollbar,体验优化,信息优先级,但是因为技术原因,完成度 50%)
- 更强大 View(彻底解决 scale 创建、同步问题,多 View 布局同步问题,自定义 controller,解耦一些逻辑)
- 交互语法(交互语法第一个版本)
- 细粒度动画(可自定义图形的动画,但是目前来看,很少开发者去使用)
- 暗黑主题(3.5 也有)
但是同时也丢失了一些有点和特性:
- DataSet 数据驱动
- 精良的文档(普遍反馈的 3.x 文档更优)
- html 类组件(label、legend、annotation)
G2 4.0 获得了一些新特性,但是也丢失了一些特性。而对于存量的布局问题,依然没有解决。
我们要做什么?
G2 优势(核心竞争力):
- 图形语法:静态渲染,学术友好,数据分析友好
- 强交互:动态,交互语法
- 强扩展:业务灵活自定义
G2 = Layout(Geometry, Component) Interaction Animation
Geometry = Attribute Shape Coordinate
Component = Axis + Legend + Tooltip + Label + Annotation + Slider + Scrollbar + Timeline
Interaction = ?
所以:
- 一些从 3.x 遗留下来的布局、响应式问题,到 4.x 依然无解
- 组件自定义能力
- legend、tooltip、annotation、label、toolbar…
- 交互:交互语法究竟是什么?
- 学术
- 业务(工业)
- 底层包工程、性能、质量
- scale
- coordinate
- adjust
- attr
- …
- 新特性
- 时序
- 统计
- 多种交互语法扩展
- 分段 scale
具体怎么做?
介绍几个核心点的做法。
布局
目前的布局逻辑 auto padding,图形有 padding,位置给组件。
- 将组件放到 0, 0 位置,去自由渲染,得到每个组件的 width 和 height
- 得到组件的宽和之后,通过组件的 position 范围,以及布局逻辑,计算出对应的 x y 以及 auto padding
- done
问题
- 组件的信息响应式处理,这里的逻辑是矛盾的!
矛盾点:
- 组件自由伸展,宽高作为组件的宽高
- 上述优先级逻辑 又需要在 一个固定的宽高中执行
所以解法是:加了一个很晦涩的 verticalLimitLength 配置。表示可以自由伸展的最大范围。组件内部约束 和 组件外部约束 互相影响,让布局逻辑非常复杂。
- 两次计算(3.x 两次渲染)
先移动到 (0, 0) 位置,伸展开计算 width height,然后布局逻辑之后,获得 x y,移动到 (x, y) 位置。这里有两次
- 两次渲染的上下文环境并不完全一致,所以导致的布局问题
竞品调研
- echarts
- 组件的 rotate 是确定的,而不是自动 auto 的
- ellipsis 一定是有确定的宽和高
- 其他情况,抽样隐藏逻辑
- 默认的 grid 逻辑是:绝对像素 / 百分比
也有不少的 bug:
- highcharts
- rotation = 0 配置默认的旋转,布局
- 碰撞后,autoRotation 可自动旋转
- 旋转还不行就省略(x 轴省略,y 永不省略)
解法
布局的问题来源是组件 + 布局算法。
归纳一下:
- 在约束条件下,求解数所有组件的 x y width height
- 所有的组件在给定的绝对 width height 下处理好自己的响应式
- 响应式的过程有一个优先级
- 组件
所有组件都有自己的 x y width height,以及 move 函数。
type AxisLabelCfg = {
rotate: number[];
ellipsis: boolean;
hide: boolean;
overlapOrder: string[]; // ['rotate', 'hide']
}
- 布局
参考之前 SEEConf 的分享,使用约束布局的逻辑,将布局逻辑算术化。(牛逼吹出去了,但是其实还并没有实现!)
交互
问题:
- 目前的交互语法是基于一个交互阶段的封装,是否是最终解、最优解?
- 对于可视分析并不友好!(筛选、联动的是数据,而不是 event + action)
- 阻断扩展
解法:
在我们暂时无法判断什么是最优的时候,内置打个样,不阻断社区扩展,让社区去选择!(虽然目前 AntV 也没有什么社区)
自定义能力(组件)
增强外置 HTML 绘制能力。
tooltip
现在 tooltip 有的自定义:
- formatter
- customItems
- customContent ❌
- tooltip:change ❌
legend
现有图例的自定义:1、formatter 2、items ❌
- 布局(位置、大小、边距、多行分页展示…)
- 内容(缺省展示、tooltip 展示…)
- 交互(高亮、数据过滤…)
- 事件(目前有,需要规范下回调参数)
- 自定义(目前需要全部重新自定义,无法基础已有的内容进行自定义,如:指标卡图例)
annotation
现有辅助标记有:
- 文本、线、dateRange、dataMarker、shape、html 等自定义
- 获取图表实例信息 ❌
言而总之:内置常见的,但是让开发者能够自己的开发,基于合理的机制,做出自己业务需要的效果。
- 生命周期事件
- 规范的获取实例数据 API
- 实例操作 API(筛选、高亮)
label
- type
- layout
- 自定义
性能
渲染性能
- scale 数据性能 ✅
- label 碰撞检测性能 ✅
- label 碰撞检测异步化
- 数据处理异步化(不卡 UI)
- G 层渲染性能
交互性能
- G 事件拾取性能优化
- G 层的按需渲染、分片渲染
- G2 render、update 合并
统计图表的性能优化,手段其实很成熟,照着火焰图直接优化。对于核心的性能卡点,增加性能单测(scale)。大部分都是代码逻辑上没有考虑到而已。
- X 轴 category scale 在大数据的时候,ticks 很多,axis label,但是实际其实画布肯定都显示不出来,这个时候,完全可以先抽样 500,再去做 overlap 逻辑。
- category scale 映射枚举值为索引,大量循环使用 indexOf,只需要一个 o(1) 的缓存就可以将 o(n^2) 变成 o(n)。