Skip to content

Commit ea0bbfa

Browse files
authored
feat(custom Shape): 添加 Shape 文档 以及 添加 三个 自定义 Shape demo (#3246)
Co-authored-by: ai-qing-hai <[email protected]>
1 parent c6b941a commit ea0bbfa

File tree

12 files changed

+847
-2
lines changed

12 files changed

+847
-2
lines changed

docs/api/options/shape.en.md

+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
---
2+
title: 图表形状
3+
order: 3
4+
---
5+
6+
#### 使用方式
7+
8+
## 简介
9+
10+
Shape is built in to configure general graphics requirements. Custom Shapes work well for some **highly customized** graphical visualization needs.
11+
12+
<b>Chart shapes can be configured in four ways:</b>
13+
14+
The first,pass `string` to set the built-in Shape.
15+
16+
```ts
17+
// 柱状图/条形图
18+
shape: 'hollow-rect' | 'tick';
19+
// 散点图
20+
shape: 'cicle' | 'square';
21+
// 其他内置 shape: circle, square, bowtie, diamond, hexagon, triangle,triangle-down, hollow-circle, hollow-square, hollow-bowtie,hollow-diamond, hollow-hexagon, hollow-triangle, hollow-triangle-down, cross, tick, plus, hyphen, line
22+
```
23+
24+
The second,pass `[]` to set Shape.
25+
26+
```ts
27+
// 区分的字段
28+
shapeField: 'x';
29+
// 更具区分的字段 区分形状
30+
shape: ['circle', 'square'];
31+
```
32+
33+
The third,pass `callback` to set Shape.
34+
35+
```ts
36+
// 区分的字段
37+
shapeField: 'x';
38+
// 回调区分形状
39+
shape: (x) => {
40+
if(x === '2020'){
41+
return 'circle';
42+
}
43+
// TODO
44+
return 'square';
45+
};
46+
```
47+
48+
The fourth, `G2.registerShape` custom Shape.
49+
50+
```ts
51+
import { G2 } from '@antv/g2plot';
52+
53+
// 往 interval 几何标记上注册名为 'line' 的 shape
54+
G2.registerShape('interval', 'line', {
55+
// 定义 line 的关键点
56+
getPoints(shapePoint: ShapePoint) {
57+
return getLinePoints(shapePoint);
58+
},
59+
// 图形具体的绘制代码
60+
draw(cfg: ShapeInfo, container: IGroup) {
61+
const style = getStyle(cfg, true, false, 'lineWidth');
62+
const path = this.parsePath(getRectPath(cfg.points));
63+
const shape = container.addShape('path', {
64+
attrs: {
65+
...style,
66+
path,
67+
},
68+
name: 'interval',
69+
});
70+
71+
return shape;
72+
},
73+
// 定义图形的缩略图样式
74+
getMarker(markerCfg: ShapeMarkerCfg) {
75+
const { color } = markerCfg;
76+
return {
77+
symbol: (x: number, y: number, r: number) => {
78+
return [
79+
['M', x, y - r],
80+
['L', x, y + r],
81+
];
82+
},
83+
style: {
84+
r: 5,
85+
stroke: color,
86+
},
87+
};
88+
},
89+
});
90+
```
91+
92+
| Geometry 类型 | 描述 |
93+
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
94+
| point | 点的绘制很简单,只要获取它的坐标以及大小即可,其中的  `size`  属性代表的是点的半径。 <img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*IF_yR6LCyw4AAAAAAAAAAABkARQnAQ" style="width: 50%;"> |
95+
| line | 线其实是由无数个点组成,在 G2 中我们将参与绘制的各个数据转换成坐标上的点然后通过线将逐个点连接而成形成线图,其中的  `size`  属性代表的是线的粗细。 <img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*8YQzSpmUnEAAAAAAAAAAAABkARQnAQ" style="width: 50%;"> |
96+
| area | area 面其实是在 line 线的基础之上形成的,它将折线图中折线与自变量坐标轴之间的区域使用颜色或者纹理填充。<img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*JRyMSIpRfRwAAAAAAAAAAABkARQnAQ" style="width: 50%;"> |
97+
| interval | interval 默认的图形形状是矩形,而矩形实际是由四个点组成的,在 G2 中我们根据 pointInfo 中的 x、y、size 以及 y0 这四个值来计算出这四个点,然后顺时针连接而成。<img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*soWnSLeska8AAAAAAAAAAABkARQnAQ" style="width: 50%;"> |
98+
| polygon | polygon 多边形其实也是由多个点连接而成,在 pointInfo 中 x 和 y 都是数组结构。<img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*anXLQ72bP78AAAAAAAAAAABkARQnAQ" style="width: 50%;"> |
99+
| violin | violin 小提琴图也是由多个点连接而成。 `pointInfo` 中,x 是小提琴中心点的 x 坐标,size 是小提琴的最大宽度,而 \_size 和 y 是相同长度的 number 数组,每一对 (\_size, y) 表示小提琴图上的一个采样点。\_size 是采样点处的概率密度,即小提琴的宽度;y 是采样点在 y 轴上的位置。<img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*RB6IRobZJBoAAAAAAAAAAAAAARQnAQ" style="width: 98px;" alt="violin"> |
100+
| schema | schema 作为一种自定义的几何图形,在 G2 中默认提供了 box 和 candle 两种 shape,分别用于绘制箱型图和股票图,注意这两种形状的矩形部分四个点的连接顺序都是顺时针,并且起始点均为左下角,这样就可以无缝转换至极坐标。<img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*USWRQ4MxENAAAAAAAAAAAABkARQnAQ" style="width: 98px;"><img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*NxwVQqQsgHwAAAAAAAAAAABkARQnAQ" style="width: 92px;"> |
101+
| edge | edge 边同 line 线一致,区别就是 edge 是一个线段,连接边的两个端点即可。
102+
103+
<!-- 更详细的使用说明详见: [Shape API](../../api/register#g2register-shape)。 -->
104+
105+
## 快速上手自定义 Shape
106+
107+
以柱状图举例,几何标记 interval 会给出四个关键点(即组成矩形的四个顶点),然后将这四个点依次连接,得到每个柱子的形状。**红色圆形**标记就是几何标记点。默认的柱状图就是通过四个几何标记点,依次相连后得到的。
108+
109+
![](https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*MHASTo6s90oAAAAAAAAAAABkARQnAQ#align=left&display=inline&height=196&originHeight=196&originWidth=249&status=done&style=none&width=249)
110+
111+
下面我们就使用自定义 shape 的功能,把上面的柱状图的柱子变成三角形,即如下图所示:
112+
113+
![](https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*8MCIS7hehZsAAAAAAAAAAABkARQnAQ#align=left&display=inline&height=196&originHeight=196&originWidth=245&status=done&style=none&width=245)
114+
115+
#### 第一步,注册 'triangle' shape
116+
117+
```javascript
118+
import { G2, Column } from '@antv/g2plot';
119+
120+
G2.registerShape('interval', 'triangle', {
121+
// 1. 定义关键点
122+
getPoints(cfg) {
123+
const x = cfg.x;
124+
const y = cfg.y;
125+
const y0 = cfg.y0;
126+
const width = cfg.size;
127+
return [
128+
{ x: x - width / 2, y: y0 },
129+
{ x: x, y: y },
130+
{ x: x + width / 2, y: y0 },
131+
];
132+
},
133+
// 2. 绘制
134+
draw(cfg, group) {
135+
const points = this.parsePoints(cfg.points); // 将0-1空间的坐标转换为画布坐标
136+
const polygon = group.addShape('path', {
137+
attrs: {
138+
path: [
139+
['M', points[0].x, points[0].y],
140+
['L', points[1].x, points[1].y],
141+
['L', points[2].x, points[2].y],
142+
],
143+
...cfg.defaultStyle,
144+
},
145+
});
146+
return polygon;
147+
},
148+
});
149+
150+
const data = [
151+
{ year: '1951 年', value: 38 },
152+
{ year: '1952 年', value: 52 },
153+
{ year: '1956 年', value: 61 },
154+
{ year: '1957 年', value: 145 },
155+
{ year: '1958 年', value: 48 },
156+
];
157+
158+
const column = new Column('container', {
159+
data,
160+
xField: 'year',
161+
yField: 'value',
162+
legend: {
163+
position: 'top-left',
164+
},
165+
// 自定义 shape
166+
shape: 'triangle',
167+
});
168+
169+
column.render();
170+
```
171+
172+
上面代码中,我们进行了三步操作:
173+
174+
1. 通过 `getPoints()`   方法返回三角形的三个关键点(即三个顶点)。此时 cfg 中会传入,x, y, y0, size。其中 x, y 是柱子最高点的坐标,y0 是横坐标轴的 y 坐标,size 是柱子默认宽度。
175+
1. 得到标记点后,我们在 `draw()` 方法中拿到 cfg.points 数据和数据映射后的图形属性数据(比如 cfg.color),再通过绘图库提供的多边形图形,将三个点依次头尾相连,生成每个三角形。
176+
1. 通过 addShap 来绘制图形,addShape 的参数参考: [绘图文档](https://g.antv.vision/zh/docs/api/general/container/#addshapecfg-shapecfg)
177+
178+
> 注意:points 数据和参与 points 计算的配置项都是 0-1 空间的数据!

docs/api/options/shape.zh.md

+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
---
2+
title: 图表形状
3+
order: 3
4+
---
5+
6+
#### 使用方式
7+
8+
## 简介
9+
10+
内置 Shape 可以配置一般需求的图形。 自定义 Shape 可以很好地支持部分有 **高订制需求的** 图表可视化需求。
11+
12+
<b>图表形状配置有四种方式:</b>
13+
14+
第一种,传入 `string` 设置内置 Shape。
15+
16+
```ts
17+
// 柱状图/条形图
18+
shape: 'hollow-rect' | 'tick';
19+
// 散点图
20+
shape: 'cicle' | 'square';
21+
// 其他内置 shape: circle, square, bowtie, diamond, hexagon, triangle,triangle-down, hollow-circle, hollow-square, hollow-bowtie,hollow-diamond, hollow-hexagon, hollow-triangle, hollow-triangle-down, cross, tick, plus, hyphen, line
22+
```
23+
24+
第二种,传入 `[]` 设置 Shape
25+
26+
```ts
27+
// 区分的字段
28+
shapeField: 'x';
29+
// 更具区分的字段 区分形状
30+
shape: ['circle', 'square'];
31+
```
32+
33+
第三种,传入 `callback` 设置 Shape
34+
35+
```ts
36+
// 区分的字段
37+
shapeField: 'x';
38+
// 回调区分形状
39+
shape: (x) => {
40+
if(x === '2020'){
41+
return 'circle';
42+
}
43+
// TODO
44+
return 'square';
45+
};
46+
```
47+
48+
第四种, `G2.registerShape` 自定义 Shape
49+
50+
```ts
51+
import { G2 } from '@antv/g2plot';
52+
53+
// 往 interval 几何标记上注册名为 'line' 的 shape
54+
G2.registerShape('interval', 'line', {
55+
// 定义 line 的关键点
56+
getPoints(shapePoint: ShapePoint) {
57+
return getLinePoints(shapePoint);
58+
},
59+
// 图形具体的绘制代码
60+
draw(cfg: ShapeInfo, container: IGroup) {
61+
const style = getStyle(cfg, true, false, 'lineWidth');
62+
const path = this.parsePath(getRectPath(cfg.points));
63+
const shape = container.addShape('path', {
64+
attrs: {
65+
...style,
66+
path,
67+
},
68+
name: 'interval',
69+
});
70+
71+
return shape;
72+
},
73+
// 定义图形的缩略图样式
74+
getMarker(markerCfg: ShapeMarkerCfg) {
75+
const { color } = markerCfg;
76+
return {
77+
symbol: (x: number, y: number, r: number) => {
78+
return [
79+
['M', x, y - r],
80+
['L', x, y + r],
81+
];
82+
},
83+
style: {
84+
r: 5,
85+
stroke: color,
86+
},
87+
};
88+
},
89+
});
90+
```
91+
92+
| Geometry 类型 | 描述 |
93+
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
94+
| point | 点的绘制很简单,只要获取它的坐标以及大小即可,其中的  `size`  属性代表的是点的半径。 <img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*IF_yR6LCyw4AAAAAAAAAAABkARQnAQ" style="width: 50%;"> |
95+
| line | 线其实是由无数个点组成,在 G2 中我们将参与绘制的各个数据转换成坐标上的点然后通过线将逐个点连接而成形成线图,其中的  `size`  属性代表的是线的粗细。 <img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*8YQzSpmUnEAAAAAAAAAAAABkARQnAQ" style="width: 50%;"> |
96+
| area | area 面其实是在 line 线的基础之上形成的,它将折线图中折线与自变量坐标轴之间的区域使用颜色或者纹理填充。<img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*JRyMSIpRfRwAAAAAAAAAAABkARQnAQ" style="width: 50%;"> |
97+
| interval | interval 默认的图形形状是矩形,而矩形实际是由四个点组成的,在 G2 中我们根据 pointInfo 中的 x、y、size 以及 y0 这四个值来计算出这四个点,然后顺时针连接而成。<img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*soWnSLeska8AAAAAAAAAAABkARQnAQ" style="width: 50%;"> |
98+
| polygon | polygon 多边形其实也是由多个点连接而成,在 pointInfo 中 x 和 y 都是数组结构。<img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*anXLQ72bP78AAAAAAAAAAABkARQnAQ" style="width: 50%;"> |
99+
| violin | violin 小提琴图也是由多个点连接而成。 `pointInfo` 中,x 是小提琴中心点的 x 坐标,size 是小提琴的最大宽度,而 \_size 和 y 是相同长度的 number 数组,每一对 (\_size, y) 表示小提琴图上的一个采样点。\_size 是采样点处的概率密度,即小提琴的宽度;y 是采样点在 y 轴上的位置。<img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*RB6IRobZJBoAAAAAAAAAAAAAARQnAQ" style="width: 98px;" alt="violin"> |
100+
| schema | schema 作为一种自定义的几何图形,在 G2 中默认提供了 box 和 candle 两种 shape,分别用于绘制箱型图和股票图,注意这两种形状的矩形部分四个点的连接顺序都是顺时针,并且起始点均为左下角,这样就可以无缝转换至极坐标。<img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*USWRQ4MxENAAAAAAAAAAAABkARQnAQ" style="width: 98px;"><img src="https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*NxwVQqQsgHwAAAAAAAAAAABkARQnAQ" style="width: 92px;"> |
101+
| edge | edge 边同 line 线一致,区别就是 edge 是一个线段,连接边的两个端点即可。
102+
103+
<!-- 更详细的使用说明详见: [Shape API](../../api/register#g2register-shape)。 -->
104+
105+
## 快速上手自定义 Shape
106+
107+
以柱状图举例,几何标记 interval 会给出四个关键点(即组成矩形的四个顶点),然后将这四个点依次连接,得到每个柱子的形状。**红色圆形**标记就是几何标记点。默认的柱状图就是通过四个几何标记点,依次相连后得到的。
108+
109+
![](https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*MHASTo6s90oAAAAAAAAAAABkARQnAQ#align=left&display=inline&height=196&originHeight=196&originWidth=249&status=done&style=none&width=249)
110+
111+
下面我们就使用自定义 shape 的功能,把上面的柱状图的柱子变成三角形,即如下图所示:
112+
113+
![](https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*8MCIS7hehZsAAAAAAAAAAABkARQnAQ#align=left&display=inline&height=196&originHeight=196&originWidth=245&status=done&style=none&width=245)
114+
115+
#### 第一步,注册 'triangle' shape
116+
117+
```javascript
118+
import { G2, Column } from '@antv/g2plot';
119+
120+
G2.registerShape('interval', 'triangle', {
121+
// 1. 定义关键点
122+
getPoints(cfg) {
123+
const x = cfg.x;
124+
const y = cfg.y;
125+
const y0 = cfg.y0;
126+
const width = cfg.size;
127+
return [
128+
{ x: x - width / 2, y: y0 },
129+
{ x: x, y: y },
130+
{ x: x + width / 2, y: y0 },
131+
];
132+
},
133+
// 2. 绘制
134+
draw(cfg, group) {
135+
const points = this.parsePoints(cfg.points); // 将0-1空间的坐标转换为画布坐标
136+
const polygon = group.addShape('path', {
137+
attrs: {
138+
path: [
139+
['M', points[0].x, points[0].y],
140+
['L', points[1].x, points[1].y],
141+
['L', points[2].x, points[2].y],
142+
],
143+
...cfg.defaultStyle,
144+
},
145+
});
146+
return polygon;
147+
},
148+
});
149+
150+
const data = [
151+
{ year: '1951 年', value: 38 },
152+
{ year: '1952 年', value: 52 },
153+
{ year: '1956 年', value: 61 },
154+
{ year: '1957 年', value: 145 },
155+
{ year: '1958 年', value: 48 },
156+
];
157+
158+
const column = new Column('container', {
159+
data,
160+
xField: 'year',
161+
yField: 'value',
162+
legend: {
163+
position: 'top-left',
164+
},
165+
// 自定义 shape
166+
shape: 'triangle',
167+
});
168+
169+
column.render();
170+
```
171+
172+
上面代码中,我们进行了三步操作:
173+
174+
1. 通过 `getPoints()`   方法返回三角形的三个关键点(即三个顶点)。此时 cfg 中会传入,x, y, y0, size。其中 x, y 是柱子最高点的坐标,y0 是横坐标轴的 y 坐标,size 是柱子默认宽度。
175+
1. 得到标记点后,我们在 `draw()` 方法中拿到 cfg.points 数据和数据映射后的图形属性数据(比如 cfg.color),再通过绘图库提供的多边形图形,将三个点依次头尾相连,生成每个三角形。
176+
1. 通过 addShap 来绘制图形,addShape 的参数参考: [绘图文档](https://g.antv.vision/zh/docs/api/general/container/#addshapecfg-shapecfg)
177+
178+
> 注意:points 数据和参与 points 计算的配置项都是 0-1 空间的数据!

examples/plugin/custom-shape/API.en.md

Whitespace-only changes.

examples/plugin/custom-shape/API.zh.md

Whitespace-only changes.

0 commit comments

Comments
 (0)