自定义分面

简介

分面(Facet)是指利用 G2 提供的 View 递归嵌套能力,可以根据一定的规则对画布的分割画布,形成多个子 View,然后在子 View 中绘制对应的数据和图形,常用于多维数据分析。

G2 的分面大概的使用方式如下:

  1. const chart = new Chart({
  2. container: '#container',
  3. // ...
  4. });
  5. chart.facet(facatType, {
  6. ...facetConfig,
  7. });

目前 G2 内置的分面包括五种:

  • rect
  • list
  • matrix
  • circle
  • tree

具体的使用方式,配置数据结构,见分面文档

如果以上内置分面无法满足自己的定制需求,那么可以尝试 G2 提供的自定义分面能力。

下面我们将介绍如何开发一个自定义分面?这包括几个部分:

  • 分面子 View 的定位逻辑
  • 自定义分面机制
  • 实现自定义分面类

子 View 定位

分面的核心逻辑是将当前 View 大小,根据数据拆分成多个子 view。

G2 中 View 可以拥有多个子 view,形成无限的嵌套逻辑。而子 View 的大小通过 region 属性来确定自身大小。类型定义如下:

  1. type Point = {
  2. readonly x: number;
  3. readonly y: number;
  4. };
  5. type Region = {
  6. readonly start: Point;
  7. readonly end: Point;
  8. };

其中 start、end 中的 x y 都是 0 ~ 1 的数字,表示子 view 的位置大小占父 view 的比例。举个例子:

  1. const region = {
  2. start: { x: 0, y: 0 },
  3. end: { x: 1, y: 0.5 },
  4. };

view 的 region 为以上数据的时候,那么这个 view 占整个画布空间的上半部分。

自定义分面机制

G2 提供自定义分面能力,实现并注册一个自定义分面的机制,大概如下代码:

  1. import { registerFacet, Facet } from '@antv/g2';
  2. // 实现一个自定义分面,继承 G2 分面基类
  3. class MyFacet extends Facet {
  4. // TODO 实现自己的分面逻辑
  5. }
  6. // 注册自定义分面到 G2 中
  7. registerFacet('my-facet', Facet);
  8. // 消费自己的自定义分面
  9. const chart = new Chart({
  10. /*...*/
  11. });
  12. chart.facet('my-facet', {
  13. /* facetConfig */
  14. });

实现自定义分面

基于上面自定义分面机制,实现自定义分面的核心内容就是开发自定义分面类 MyFacet

  1. import { Datum, Facet, FacetCfg, FacetData, View } from '@antv/g2';
  2. interface MyFacetCfg extends FacetCfg {
  3. // TODO
  4. }
  5. interface MyFacetData extends FacetData {
  6. // TODO
  7. }
  8. class MyFacet extends Facet<MyFacetCfg, MyFacetData> {
  9. protected afterEachView(view: View, facet: MyFacetCfg) {}
  10. protected beforeEachView(view: View, facet: MyFacetCfg) {}
  11. protected generateFacets(data: Datum[]): MyFacetCfg[] {
  12. return [];
  13. }
  14. protected getXAxisOption(
  15. x: string,
  16. axes: any,
  17. option: object,
  18. facet: MyFacetCfg,
  19. ): object {
  20. return undefined;
  21. }
  22. protected getYAxisOption(
  23. y: string,
  24. axes: any,
  25. option: object,
  26. facet: MyFacetCfg,
  27. ): object {
  28. return undefined;
  29. }
  30. }

1. 类型定义

首先定义 Facet 的配置 MyFacetCfg、分面数据的类型定义 MyFacetData。

2. 继承基类

继承 G2 提供的基类 Facet,Facet 有 5 个抽象方法必须实现,分别是:

  • beforeEachView
  • afterEachView
  • generateFacets
  • getXAxisOption
  • getYAxisOption
  • beforeEachView、afterEachView

是初始化每一个子分面 view 的时候的钩子函数,可以用来使用 G2 的 annotation 绘制一些标题等信息。

  • generateFacets generateFacets 是自定义分面的核心方法。方法返回一个分面数据的数组,每一个分面数据中包含:
  • data:分面子 view 的数据
  • region:分面子 View 的位置大小信息
  • 分面标记信息:比如 rect 中行列 index
  • 其他信息:比如 rect 中,行列的分面字段 field 等等
  • getXAxisOption、getYAxisOption

是根据每个分面来决定是否显示分面 view 中的坐标轴组件。

3. 注册使用

利用 G2 的自定义分面机制来消费使用。

  1. import { registerFacet } from '@antv/g2';
  2. // 注册
  3. registerFacet('my-facet', MyFacet);
  4. // 使用
  5. chart.facet('my-facet', MyFacetCfg);

源码参考

具体的实现逻辑,可以参考 G2 源码中 rect 分面的实现逻辑。