背景
分面(Facet)的核心逻辑是按照数据字段,和分片逻辑将当前 view 切分成几个部分,每个部分会生成一个子 view,配合 view 递归嵌套的能力,可以画布区域进行灵活的分片和布局。
G2 将内置以下分面形式:
- circle
 - list
 - matrix
 - mirror
 - rect
 - tree
 
API
API 是很简单的,在 view 上新增 facet API,可以指定使用某一个分面方式去做分面,并传入分面的配置。
view.facet(type: string, cfg: FacetCfg) {};
实现
view
- 增加 facet API
 - view 生命周期执行分面逻辑
 - render
 - changeData
 
facet 基类
facet 基类确定了 facet 的生命周期,以及后续分面的扩展。
生命周期
initial
[x] 初始化过程,初始化 G 容器
[x] 按照分面字段,将数据分片,形成分面数据 FacetData,这个数据最终用来生成分面子 View
render
[x] 将 FacetData 渲染成子 View,执行 eachView 的逻辑
- 然后根据数据生成 title、axis、legend 等一些辅助 UI
 - title
 - axis
 [ ] legend
destroy
[x] 移除 G 容器
- 关闭事件
 - 清空数据,view 等
 
facet 构造参数
class Facet {// 构造函数constructor(view: View, cfg: FacetCfg) {// ...}}/*** 默认的基础配置*/export interface FacetCfg {// 布局类型readonly type?: string;// view 创建回调readonly eachView: (innerView: View, facet?: FacetData) => any;// facet 间距readonly padding?: number;// 子 view 的 paddingreadonly viewPadding?: number;}
- 构造函数由两个参数,第一个为父级 view,第二个为 facet 实例的配置
 - 基类 facet 配置定义结构为 FacetCfg,子类的配置结构继承于它
 
布局
分面布局分成为几部分:
- facet 区域布局
- facet 区域其实就是 view 的绘图区大小
 
 - 子 view 的布局
- 按照分面字段,均分区域 region
 - padding 字段来决定 view 之间的 padding
 - margin 字段决定 view 的 margin
 
 - title axis 等组件布局
- 将 title axis 放置到 margin 区域中
 
 
rect
内置的矩形分面。
构造参数
/*** rect 分面的配置*/export interface RectCfg extends FacetCfg {// column, rowreadonly fields: [string, string];}
在基类配置的基础上,增加 fields 分面字段信息。
- 继承 Facet 基类,实现数据分面
 - 实现 title
 - 实现 axis
 - 实现 legend
 
渲染和布局过程
在 render 过程中的执行逻辑。分面的 render 是 view 嵌套逻辑中的一个子环节,可以到 布局逻辑 文档查看整体的流程。

在 initial 阶段,已经通过分面字段,计算除了分面数据,分面数据包含:
- 分面 region
 - 分面数据
 - 分面索引
 
在 render 阶段做的事情包括:
- 渲染分面组件
- 根据分面索引,获取上右下左四个方向贴边的分面数据
 - 根据贴边分面数据,生成组件
- 左、下方生成 axis 组件
 - 上、右方生成 title 组件
 
 - 非贴边的分面,生成 x axis 组件
 - 所有组件都放置到 FORE layer(view 三层中的顶层)
 
 - 布局分面组件
- 根据四个方向的组件,计算上右下左四个方向 gap
 - 更新 view 的 coordinateBBox,去除 gap
 - 遍历组件,将组件 move 到 coordinateBBox 的四个方向上
 
 - 渲染分面 views
- 根据分面数据,view.createView 生成子 view
 - 设置子 view 数据
 - 执行 eachView 逻辑,设置子 view 中的 Geometry
 
 
然后在 view 的 render 流程中会递归渲染子 view(也就是分面生成的 view)。
