Skip to content

Commit 4b3143e

Browse files
authored
docs: 增加一个漏斗图分析 demo (#2848)
1 parent 7fb1542 commit 4b3143e

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import React, { useRef, useEffect } from 'react';
2+
import ReactDOM from 'react-dom';
3+
import { Funnel } from '@antv/g2plot';
4+
import insertCss from 'insert-css';
5+
6+
const formatter = (v) => `${(v * 100).toFixed(2)}%`;
7+
8+
const Plot = () => {
9+
const data = [
10+
{ stage: '简历投递数', count: 3511 },
11+
{ stage: '简历评估通过数', count: 1024 },
12+
{ stage: '终面通过数', count: 148 },
13+
{ stage: 'offer 数', count: 119 },
14+
{ stage: '入职数', count: 70 },
15+
].map((d) => ({ ...d, _count: 1 }));
16+
17+
const chartNodeRef = useRef();
18+
const plotRef = useRef();
19+
20+
const renderAnntations = (plot) => {
21+
const { chart } = plot;
22+
const coord = chart.getCoordinate();
23+
const elements = chart.geometries[0].elements;
24+
const parsePoints = [];
25+
elements.forEach((ele, idx) => {
26+
const { points, nextPoints } = ele.shape.get('origin');
27+
if (nextPoints) {
28+
let p0 = { y: (points[1].y + points[2].y) / 2 };
29+
if (idx > 0) {
30+
p0.x = parsePoints[idx - 1][1].x;
31+
} else {
32+
p0.x = (points[2].x + points[1].x) / 2;
33+
}
34+
let p3 = { x: (nextPoints[2].x + nextPoints[1].x) / 2, y: (nextPoints[2].y + nextPoints[1].y) / 2 };
35+
parsePoints.push([p0, p3]);
36+
}
37+
});
38+
let container = chart.getLayer('fore').findById('annotation-group');
39+
if (!container) {
40+
container = chart.getLayer('fore').addGroup({ id: 'annotation-group' });
41+
} else {
42+
container.clear();
43+
}
44+
parsePoints.forEach((point, idx) => {
45+
const p0 = coord.convert(point[0]);
46+
const p3 = coord.convert(point[1]);
47+
const path = [
48+
['M', p0.x, p0.y],
49+
['L', p0.x + 15, p0.y],
50+
['L', p3.x + 15, p3.y - 2],
51+
['L', p3.x, p3.y - 2],
52+
];
53+
container.addShape('path', {
54+
attrs: {
55+
path,
56+
stroke: '#d3d3d3',
57+
lineWidth: 1,
58+
},
59+
});
60+
const fontSize = 10;
61+
const offset = 5;
62+
container.addShape('text', {
63+
attrs: {
64+
x: (path[0][1] + path[1][1]) / 2 + offset,
65+
y: (path[1][2] + path[2][2] + fontSize) / 2,
66+
text: `转化率:${formatter(data[idx + 1].count / data[idx].count)}`,
67+
fontSize: 10,
68+
fill: '#333',
69+
},
70+
});
71+
});
72+
chart.render(true);
73+
};
74+
75+
useEffect(() => {
76+
// Step 2: 创建图表
77+
if (chartNodeRef && chartNodeRef.current) {
78+
const plot = new Funnel(chartNodeRef.current, {
79+
data: data,
80+
xField: 'stage',
81+
yField: '_count',
82+
legend: false,
83+
conversionTag: false,
84+
dynamicHeight: true,
85+
label: {
86+
formatter: (text, item) => {
87+
return `${item._origin.stage} ${item._origin.count}`;
88+
},
89+
},
90+
tooltip: {
91+
customItems: (items) => {
92+
return items.map((d) => ({ ...d, value: d.data.count }));
93+
},
94+
},
95+
funnelStyle: {
96+
stroke: '#fff',
97+
lineWidth: 3,
98+
},
99+
});
100+
101+
// Step 3: 渲染图表
102+
plot.render();
103+
plotRef.current = plot;
104+
}
105+
}, [chartNodeRef]);
106+
107+
useEffect(() => {
108+
const plot = plotRef && plotRef.current;
109+
if (plot) {
110+
renderAnntations(plot);
111+
plot.chart.on('afterchangesize', () => {
112+
renderAnntations(plot);
113+
});
114+
}
115+
}, [plotRef]);
116+
117+
return (
118+
<section className={'wrapper'}>
119+
<div ref={chartNodeRef} />
120+
</section>
121+
);
122+
};
123+
124+
// 我们用 insert-css 演示引入自定义样式
125+
// 推荐将样式添加到自己的样式文件中
126+
// 若拷贝官方代码,别忘了 npm install insert-css
127+
insertCss(``);
128+
129+
ReactDOM.render(<Plot />, document.getElementById('container'));

examples/case/statistical-scenario/demo/meta.json

+9
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,17 @@
1818
"zh": "场景漏斗图",
1919
"en": "Funnel Scenario"
2020
},
21+
"new": true,
2122
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/kqkXF8ap7d/24934434-0067-4c1f-9c22-e51b27beb3f6.png"
2223
},
24+
{
25+
"filename": "funnel-analysis.jsx",
26+
"title": {
27+
"zh": "自定义分析漏斗图",
28+
"en": "Funnel analysis"
29+
},
30+
"screenshot": "https://gw.alipayobjects.com/zos/antfincdn/3jrUoywaYN/339d1657-af7b-47d0-8434-da69979d597d.png"
31+
},
2332
{
2433
"filename": "pie.ts",
2534
"title": {

0 commit comments

Comments
 (0)