I didn't expect to use the custom facet function so soon, I was caught off guard.

Overview

The reason is that when the development was in the middle, we found that the effect we achieved was very inconsistent with the ideas of the product partners. The existing capabilities of the engine do not support the desired effect of the product. Well, it can only be self-reliant.

What is faceting

Facet (Facet) refers to using the View recursive nesting capability provided by G2 to divide a piece of data into several subsets according to a certain dimension, and then create a chart matrix, and draw each data subset to the window of the chart matrix. Grid.

The above is the explanation in the official document. Simply put, the canvas is divided according to certain rules to form multiple sub-views, and then the corresponding data and graphics are drawn in the sub-views.

G2 itself also has several built-in facet types, such as common list, rect, tree, etc. The usage is also very simple:

chart.facet(type: string, cfg: FacetCfg) => View

Refer to the official documentation for specific use

How to customize facets

Custom facets mainly include three core elements:

  1. Positioning logic of facet View
  2. Custom faceting mechanism
  3. Implement a custom facet class

Sub View positioning

The essence of positioning is to split a part of the canvas to the child view container.

The core logic of faceting is to split the current View size into multiple sub-views based on the data.

Views in G2 can have multiple sub-views, forming unlimited nesting logic.

Custom faceting mechanism

G2 provides the ability to customize facets, and implements and registers a mechanism for custom facets. The code is roughly as follows:

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 */
});

Implement custom facets

The core is to develop a custom facet class MyFacet, there are 5 abstract methods that must be implemented.

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;
  }
}

Built-in faceted source code analysis

Ok, understand the basic concepts related to faceting, let's analyze the logic of built-in faceting.
There is no difference between the built-in facet implementation and the custom facet implementation logic, and five abstract methods must be implemented. Let’s take a look at the implementation of the list facet first.
image.png
This is the entire code of the list facet class, which is very concise.
Let's analyze the core of the implementation of the generateFacets method for generating facet positioning:
image.png
Dividing the data into subviews of several rows and columns according to the dimension division field is such a logic.
image.png
The canvas area division is based on the number of rows and columns to score areas, which are assigned to each subview.
The remaining drawing logic is no different from ordinary graphics

The other facets are similar to this one, and the essence is how to divide the area.


donglegend
910 声望82 粉丝

长安的风何时才能吹到边梁?


引用和评论

0 条评论