简介
详细设计中需要讲清楚下面的这些内容:
- G2 的组成部分
- 数据流转
- 交互的设计
- 扩展的方式
组成部分
类结构
- 这次变化最大的是增加了 Element 这一层,Element 的详细设计参看这里:[Element 的设计]
Stat 是统计相关的类,2.x 提供的统计类在 4.x 中会回归,不过功能上会受限,不再将布局相关的在这里实现
数据流转
主要考虑几个数据流:
初始化
- 数据整体更新
- 交互中的图形变化,交互完成后的数据变化
初始化
在 g2 之前的版本中,初始化和数据整体更新的流程本质上一样,仅仅在后者需要把之前的图形清理掉。 在 g2 4.0 中,数据更新是否走更新流程还需要进行设计,这会增加很多成本,包括:
- 新数据和之前图形的匹配
- 组件的更新机制
- 图形和组件的动画机制
如果不走整体刷新的方案,则流程会变化成:
交互中的图形变化,不会去更新原始数据,而仅仅修改图形的属性。当然也可以通过更新数据重新走一遍数据更新流程来实现,但是这种方式成本非常大,如果不更新原始数据,会导致图形超出数据范围的情况发生。
交互结束后的数据变化,可以走数据整体更新的逻辑,通常来说大多是过滤。
交互的设计
g2 2.x 和 3.x 中的交互仅包括:
- active/highlight
- selected
- tooltip
- legend 筛选
这些交互逻辑基本全部写死在代码的内部,扩展性和适应性有很大问题,在 4.0 中,所有的这些交互都会写成 interaction,以一种可插拔的方式提供给用户,这里面最需要解决的问题:
- 交互不应干扰图表元素和组件的渲染
- 所有的交互都是平等的,G2 本身不内嵌任何交互
这样会精简 G2 主流程的代码,同时也会使得交互变得更加透明可控,交互详细的写法参看 交互的写法
扩展的设计
由于 G2 定位的变化,仅仅 shape 的扩展已经不能满足用户的需求,在 4.0 中我们将提供:
- 交互的扩展
- 因为引入 Element 对 shape 的扩展进行改造
- 组件的扩展,对 Axis,Tooltip,Legend,annotation, label 进行扩展
- 动画的扩展机制,需要同时考虑图表的图形元素和组件的图形元素的动画
- 映射过程中的扩展:scale, coord 的扩展
交互的扩展
交互的扩展牵扯的内容非常多,在独立章节中讨论,参考 交互的写法
自定义 Shape 的改造
自定义 shape 需要进行以下改造:
- 将单个 shape(canvas) 改造成 group
- 能够对状态进行响应,例如 active, selected, dark 等
- 能够通过继承复写现有的 shape
基本的设计理念将与 G6 一致,只是更加简单一些,最终的 API 可能是这样:
G2.registerShape('interval', 'my-interval', {
draw(cfg, group) {
},
setState(name, value, element) {
}
}, 'rect');
chart.interval().position('x*y').shape('my-interval');
组件的扩展
目前来看,label, annotation(guide) 的扩展需求最为旺盛,而 axis, legend, tooltip 更多的是内容格式化需求,组件的扩展目前的设计比较简单,基于现有组件进行扩展,然后注册到组件的命名空间上即可:
const Component = require('@antv/component');
const Axis = Component.Axis;
class MyAxis extends Axis.Line {
}
// 注册到命名空间
Axis.MyAxis = MyAxis;
// 使用
chart.axis('xxx', {
type: 'myAxis',
...
});
- 优点:简单、容易理解;
- 缺点:理解要继承的类的结构和能扩展的方法,类设计时需要考虑用户的扩展需求
动画的扩展机制
暂时还没想好,2.x ,3.x 的扩展机制第三方用户并没有太多使用,需要把更多动画进行拆解,让用户更容易的定制动画。
映射过程中的扩展
scale 的扩展可以实现很多 G2 没有提供的功能:
- 非均匀度量
- 对称度量
- 自己定义的周期性(周、月、年)的度量
scale 本质上在 2.x 开始用户就可以去扩展,只是没有在 api 中开放出来,直接在度量定义中复写其中的 scale 和 invert 方法即可:
chart.scale('field', {
type: 'linear',
scale(value) {},
invert(value) {}
});
- 这种方案扩展的 scale 每个图表上都需要写一遍,无法复用,所以更好的方案同组件的扩展一致
const Scale = require('@antv/scale');
const Custom extends Scale.Linear {
scale(value) {},
invert(value) {}
}
// 使用时
chart.scale('xxx', {type: 'custom'});
总结
本章节,对 G2 4.0 的详细设计进行了粗略的介绍,这里面每个小结都需要进行细化,这些设计决定了用户可以理解的信息,也决定了用户使用 G2 的体验,欢迎大家参与讨论,让 G2 真正的成为易用、无限可能的图形语法、交互语法、动画语法。