没想到这么快就要使用自定义分面Facet功能了,猝不及防。
概述
起因是开发进行到一半的时候,发现 我们实现的效果 和 产品小伙伴的想法很不一致。而引擎现有能力并不支持产品想要的效果。嗯,只能自力更生了。
什么是分面
分面(Facet)是指利用 G2 提供的 View 递归嵌套能力,将一份数据按照某个维度分隔成若干子集,然后创建一个图表的矩阵,将每一个数据子集绘制到图表矩阵的窗格中。
上面是官方文档里的解释,简单讲就是 根据一定的规则对画布进行分割,形成多个子 View,然后在子 View 中绘制对应的数据和图形。
G2本身也内置了几种分面类型,如常见的list,rect,tree等,使用方式也很简单:
chart.facet(type: string, cfg: FacetCfg) => View
具体参考官方文档使用
如何自定义分面
自定义分面主要包含三个核心要素:
- 分面子 View 的定位逻辑
- 自定义分面机制
- 实现自定义分面类
子 View 定位
定位实质就是 分割出画布上的一部分给子view容器。
分面的核心逻辑是将当前 View 大小,根据数据拆分成多个子 view。
G2 中 View 可以拥有多个子 view,形成无限的嵌套逻辑。
自定义分面机制
G2 提供自定义分面能力,实现并注册一个自定义分面的机制,大概如下代码:
import { registerFacet, Facet } from '@antv/g2';
// 实现一个自定义分面,继承 G2 分面基类
class MyFacet extends Facet {
// TODO 实现自己的分面逻辑
}
// 注册自定义分面到 G2 中
registerFacet('my-facet', Facet);
// 消费自己的自定义分面
const chart = new Chart({
/*...*/
});
chart.facet('my-facet', {
/* facetConfig */
});
实现自定义分面
核心就是开发自定义分面类 MyFacet,有5 个抽象方法必须实现。
import { Datum, Facet, FacetCfg, FacetData, View } from '@antv/g2';
interface MyFacetCfg extends FacetCfg {
// TODO
}
interface MyFacetData extends FacetData {
// TODO
}
class MyFacet extends Facet<MyFacetCfg, MyFacetData> {
protected afterEachView(view: View, facet: MyFacetCfg) {}
protected beforeEachView(view: View, facet: MyFacetCfg) {}
protected generateFacets(data: Datum[]): MyFacetCfg[] {
return [];
}
protected getXAxisOption(x: string, axes: any, option: object, facet: MyFacetCfg): object {
return undefined;
}
protected getYAxisOption(y: string, axes: any, option: object, facet: MyFacetCfg): object {
return undefined;
}
}
内置分面源码分析
ok,了解了分面相关的基本概念,我们来分析一下内置分面的逻辑。
内置分面实现和自定义分面实现逻辑并无不同,也是必须实现5个抽象方法,我们先看一下 list分面的实现。
这就是list分面类全部的代码了,很简洁。
我们核心分析一下 生成分面定位的 generateFacets 方法实现:
根据维度分割字段把数据划分成 几行几列的 子view,就是这么个逻辑。
画布区域划分就是根据行数和列数 评分区域,分配给每个子view。
剩余的绘制逻辑就和 普通图形没有区别了
其他几个分面 和这个都大同小异,本质就是如何 划分区域的问题。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。