View 是 G2 的画布容器,里面会包含 Geometry,组件,交互,事件等;而 Chart 是继承 View,直接暴露给开发者的便捷使用入口。
从几个点去做 View 的详细设计:
- 类图结构
- 组件、几何图形的关系
- 数据处理
- 事件
- 布局
- 生命周期
1. 类图结构
整体上 Chart 继承自 View,功能上 Chart 和 View 区别不大。区别点包括:
- Chart 需要接受 dom / selector string 作为参数,然后创建 G.Canvas,生成三层 Group
- Chart 需要处理容器变化的时候,自适应 / 手动适应图形(ChangeSize)
类图如下:
View 主要职责:
- 子 view、子组件、子几何图形的管理
- 生命周期(initial、render、clear、destroy)
- 设置配置的 API(比如数据、组件配置等、scale 配置)
- 布局
- 一些获取信息的 get API
- 事件
2. 生命周期职责
目前整理是四个周期:initial、render、clear、destroy。各个周期的职责和内容包括:
- initial
- 处理 region
- 绑定事件
- 一些默认的初始配置
- render
- 递归 views 渲染
- 数据处理(filter)
- 创建 coordinate
- 构建画布(通过配置生成组件和 Geometry,geometry 数据处理(initial 阶段)完成)
- component
- axes
- legend
- geometry
- component
- 布局(layout 执行)
- 绘制(canvan.draw)
- clear
clear 和 destroy 区别在于,clear 之后可以通过 initial、render 方法再次使用。
- 清空 views、components、geometries
- 取消绑定事件
- 配置复原
- destroy
理论上,只能在动态渲染中,动态增删 view 会用到。
- clear
- 从 parent 中移除,销毁自己
生命周期的流程图如下:
3. 组件、Geometry 关系
View 管理子 view,子组件、子图形。
每个 view 中可以嵌套多个子 view,且可以包含多个组件和图形,具体这些组件和图形是什么,view 不会具体去关心。
至于说组件放到 View,还是放到顶层 Chart,由 controller 去控制和决定,View Chart 本身 API 不感知这个逻辑。
另外,对于组件 Components,还需要告诉 view 他的层级、方位。这些信息仅仅用于后续去生成实例、布局。
addComponent(component: Component, layer: LAYER = LAYER.MID, direction: DIRECTION = DIRECTION.BOTTOM): void
4. 数据处理
View 负责数据的 API 有两个(后续不排除会增加):
- view.data
- view.filter
view 中的 data 是原始的数据,经过 filter 处理之后,会传给 Geometry 按照图形语法的方式,进行数据到图形的映射流程。
所以 view 这层提供的数据处理非常简单,目前仅仅只有过滤,可以通过扩展 view api 来扩展数据处理能力。
筛选器结构:
export type FilterCondition = (value: any, datum: Datum) => boolean;
5. 事件
View 在事件上会做两个事情:
- 监听他管理的 components、geometries 的事件。比如 legend:itemchange,interval:mouseover 等
- 事件冒泡。也就是 chart 上可以监听到所有 components、geometries 的所有事件
name:event
组件事件名的逻辑,会直接包到底层 G 模块中。暂不知道如何实现?
6. 布局
布局:是对 view 中的 Views、Components、Geometries,根据配置(Region、Direction 等信息)计算出他们实际的位置和大小,并保证无遮挡、裁剪等问题。
Layout 是一个单纯的函数(简化概念):
export type Layout = (view: View) => void;
用户可以通过 view.setLayout 来指定自己的 layout 逻辑。G2 会内置一套处理 axis、legend、Geometry、分面 的布局逻辑。
- 根据子 view 的配置 range,可以计算出子 view 的位置大小;
- 根据 view 的大小位置,以及 legend 的 direction,计算出 legend 的位置 x,y;
- 根据 axis 内容不遮挡原则,计算出 yaxis 的 width,xaxis 的 height;
- 剩余的位置给 Geometry,确定 Geometry 的 位置大小,然后可以反向计算出 yaxis 的 height、xaxis 的 width;以及他们的位置 x,y 信息;
- 递归计算子 views 的布局;
开发者可以基于 G2 的 layout,追加自己的一些调整逻辑。或者完全自定义。