Skip to content

Commit cf5dfcd

Browse files
authored
feat: add forward pyramid diagram (#7232)
1 parent fdc30a6 commit cf5dfcd

11 files changed

Lines changed: 444 additions & 4 deletions

File tree

Lines changed: 140 additions & 0 deletions
Loading
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { G2Spec } from '../../../src';
2+
3+
export function alphabetIntervalPyramidReverse(): G2Spec {
4+
return {
5+
type: 'interval',
6+
coordinate: {
7+
transform: [{ type: 'transpose' }],
8+
},
9+
data: [
10+
{ text: '页面', value: 200 },
11+
{ text: '页面1', value: 400 },
12+
{ text: '页面2', value: 600 },
13+
{ text: '页面3', value: 800 },
14+
],
15+
transform: [
16+
{
17+
type: 'symmetryY',
18+
},
19+
],
20+
axis: {
21+
x: false,
22+
y: false,
23+
},
24+
style: {
25+
stroke: '#ff0000',
26+
reverse: true,
27+
},
28+
encode: {
29+
x: 'text',
30+
y: 'value',
31+
color: 'text',
32+
shape: 'pyramid',
33+
},
34+
scale: {
35+
x: { paddingOuter: 0, paddingInner: 0 },
36+
color: { type: 'ordinal', range: ['red', 'green', 'blue', '#e45ca2'] },
37+
},
38+
};
39+
}

__tests__/plots/static/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export { alphabetIntervalLabelOverflowStroke } from './alphabet-interval-label-o
1313
export { alphabetIntervalDataSort } from './alphabet-interval-data-sort';
1414
export { alphabetIntervalFunnel } from './alphabet-interval-funnel';
1515
export { alphabetIntervalPyramid } from './alphabet-interval-pyramid';
16+
export { alphabetIntervalPyramidReverse } from './alphabet-interval-pyramid-reverse';
1617
export { bodyPointScatterPlot } from './body-point-scatter-plot';
1718
export { bodyPointScatterPlotSizeOpacity } from './body-point-scatter-plot-size-opacity';
1819
export { bodyPointScatterPlotOpacity } from './body-point-scatter-plot-opacity';

site/docs/charts/funnel.en.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,74 @@ chart.render();
279279
- Consistent color coding for corresponding stages facilitates comparison
280280
- You can clearly observe differences in conversion efficiency across channels at various stages
281281

282+
Example 4: **Intuitive and Visual Chart Form, Often Used to Display Hierarchical Structures or Distribution Proportions**
283+
284+
Company hierarchy pyramid structure, where employees are divided into multiple levels based on their rank, with significant differences in population proportions, responsibilities, and authority across levels, intuitively reflecting the hierarchical differentiation within the company.
285+
286+
```js | ob { inject: true }
287+
import { Chart } from '@antv/g2';
288+
289+
const chart = new Chart({
290+
container: 'container',
291+
theme: 'classic',
292+
});
293+
294+
chart.options({
295+
type: 'interval',
296+
coordinate: {
297+
transform: [{ type: 'transpose' }],
298+
},
299+
data: [
300+
{ text: 'Top Level', value: 5 },
301+
{ text: 'Upper Middle', value: 10 },
302+
{ text: 'Middle', value: 20 },
303+
{ text: 'Lower Middle', value: 25 },
304+
{ text: 'Bottom Level', value: 40 },
305+
],
306+
transform: [
307+
{
308+
type: 'symmetryY',
309+
},
310+
],
311+
axis: {
312+
x: false,
313+
y: false,
314+
},
315+
style: {
316+
reverse: true,
317+
},
318+
encode: {
319+
x: 'text',
320+
y: 'value',
321+
color: 'text',
322+
shape: 'pyramid',
323+
},
324+
scale: {
325+
x: { paddingOuter: 0, paddingInner: 0 },
326+
color: { type: 'ordinal' },
327+
},
328+
labels: [
329+
{
330+
text: (d) => d.text,
331+
position: "inside"
332+
},
333+
{
334+
text: (d) => d.value + "%",
335+
position: "inside",
336+
style: { dy: 15 }
337+
},
338+
]
339+
})
340+
341+
chart.render();
342+
```
343+
344+
**Explanation**:
345+
- Uses `reverse: true` to change the narrowing position of the funnel chart
346+
- Population proportions should decrease layer by layer, reflecting the "wide bottom, narrow top" structure
347+
- Population percentages for each level are clearly labeled, facilitating comparison of quantities or proportions between different groups
348+
- Pyramid shape intuitively displays hierarchical distribution and stratification characteristics
349+
282350
### Unsuitable Use Cases
283351

284352
Example 1: **Not Suitable for Unordered Data or Data Without Clear Hierarchy**

site/docs/charts/funnel.zh.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,75 @@ chart.render();
275275
- 通过相同的颜色编码对应相同的阶段,便于比较
276276
- 可以清晰地观察到不同渠道在各个阶段的转化效率差异
277277

278+
例子 4:**直观、形象的图表形式,常用于展示层级结构或分布比例**
279+
280+
公司职级金字塔结构,根据职级高低将员工划分为多个层级,各层级在人数比例、职责与权限上存在显著差异,直观体现了公司内部的层级分化情况。
281+
282+
```js | ob { inject: true }
283+
import { Chart } from '@antv/g2';
284+
285+
const chart = new Chart({
286+
container: 'container',
287+
theme: 'classic',
288+
});
289+
290+
chart.options({
291+
type: 'interval',
292+
coordinate: {
293+
transform: [{ type: 'transpose' }],
294+
},
295+
data: [
296+
{ text: '顶层', value: 5 },
297+
{ text: '中上层', value: 10 },
298+
{ text: '中等', value: 20 },
299+
{ text: '中下层', value: 25 },
300+
{ text: '底层', value: 40 },
301+
],
302+
transform: [
303+
{
304+
type: 'symmetryY',
305+
},
306+
],
307+
axis: {
308+
x: false,
309+
y: false,
310+
},
311+
style: {
312+
reverse: true,
313+
},
314+
encode: {
315+
x: 'text',
316+
y: 'value',
317+
color: 'text',
318+
shape: 'pyramid',
319+
},
320+
scale: {
321+
x: { paddingOuter: 0, paddingInner: 0 },
322+
color: { type: 'ordinal' },
323+
},
324+
labels: [
325+
{
326+
text: (d) => d.text,
327+
position: "inside"
328+
},
329+
{
330+
text: (d) => d.value + "%",
331+
position: "inside",
332+
style: { dy: 15 }
333+
},
334+
]
335+
})
336+
337+
chart.render();
338+
```
339+
340+
**说明**
341+
- 使用 `reverse: true` 改变漏斗图收口位置
342+
- 人数比例应逐层递减,反映“底宽顶尖”的结构
343+
- 各层级人口占比清晰标注,便于比较不同群体的数量或比例
344+
- 金字塔形状直观展现阶层分布和分层特点
345+
346+
278347
### 不适合的场景
279348

280349
例子 1: **不适合展示无序或无明显层级关系的数据**

site/docs/manual/core/mark/interval.en.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ Configure the style of the `interval` mark.
455455
| shadowBlur | Gaussian blur coefficient of the graphic shadow | number \| (d, index, data, column) => number | - | |
456456
| shadowOffsetX | Horizontal distance of the shadow from the graphic | number \| (d, index, data, column) => number | - | |
457457
| shadowOffsetY | Vertical distance of the shadow from the graphic | number \| (d, index, data, column) => number | - | |
458+
| reverse | Set the narrowing direction for funnel and pyramid charts (added in v5.4.8) | boolean | `false` | |
458459
| cursor | Mouse cursor style. Same as CSS cursor style. | string \| (d, index, data, column) => string | `default` | |
459460

460461
Try it out:
@@ -492,8 +493,8 @@ chart.options({
492493
radiusTopLeft: 20,
493494
radiusTopRight: 20,
494495
insetBottom: 5,
495-
// 绘图属性
496-
fill: (d) => (d.name === 'London' ? '#688FD4' : '#55BECC'), // 绘图属性也可以是一个回调函数
496+
// Drawing properties
497+
fill: (d) => (d.name === 'London' ? '#688FD4' : '#55BECC'), // Drawing properties can also be callback functions
497498
fillOpacity: 0.9,
498499
stroke: '#fff',
499500
lineWidth: 1,

site/docs/manual/core/mark/interval.zh.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ chart.render();
456456
| shadowBlur | `interval` 图形阴影的高斯模糊系数 | number \| (d, index, data, column) => number | - | |
457457
| shadowOffsetX | 设置阴影距`interval` 图形的水平距离 | number \| (d, index, data, column) => number | - | |
458458
| shadowOffsetY | 设置阴影距`interval` 图形的垂直距离 | number \| (d, index, data, column) => number | - | |
459+
| reverse | 设置漏斗图、金字塔图的收口方向 (v5.4.8 版本新增) | boolean | `false` | |
459460
| cursor | 鼠标样式。同 css 的鼠标样式。 | string \| (d, index, data, column) => string | `default` | |
460461

461462
尝试一下:

site/examples/general/funnel/demo/meta.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@
2828
},
2929
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*VpuRSZGqnlUAAAAAAAAAAAAADmJ7AQ/original"
3030
},
31+
{
32+
"filename": "pyramid-forward.ts",
33+
"title": {
34+
"zh": "正向金字塔图",
35+
"en": "pyramid-forward"
36+
},
37+
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*oKnDQINKBvAAAAAAQpAAAAgAemJ7AQ/original"
38+
},
3139
{
3240
"filename": "mirror-funnel.ts",
3341
"title": {

0 commit comments

Comments
 (0)