Skip to content

example(compare funnel): 添加了对比漏斗图案例 #2859

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
277 changes: 277 additions & 0 deletions examples/case/statistical-scenario/demo/compare-funnel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
import { G2, P } from '@antv/g2plot';
import { deepMix } from '@antv/util';

const currDate = ['2020-08-01'];
const compareDate = ['2020-07-06'];
const name = ['本期', '对比期'];
const tooltipItemsName = ['本期留存', '本期流失', '对比期留存', '对比期流失'];

const columnColor = [
{
transformed: '#3b89ff',
'non-transformed': '#e1eeff',
increased: '#e1eeff',
},
{
transformed: '#4ccaa1',
'non-transformed': '#defbf1',
increased: '#defbf1',
},
];
const rawData = [
{ date: '2020-08-01', index: '投放点击用户数', type: '本期', value: 46893 },
{ date: '2020-08-01', index: '会场曝光用户数', type: '本期', value: 37896 },
{ date: '2020-08-01', index: '会场点击用户数', type: '本期', value: 34896 },
{ date: '2020-08-01', index: '权益领取用户数', type: '本期', value: 28896 },
{ date: '2020-08-01', index: '引导IUV', type: '本期', value: 14896 },
{ date: '2020-08-01', index: '引导成交用户数', type: '本期', value: 4755 },
{ date: '2020-07-06', index: '投放点击用户数', type: '对比期', value: 46893 },
{ date: '2020-07-06', index: '会场曝光用户数', type: '对比期', value: 37896 },
{ date: '2020-07-06', index: '会场点击用户数', type: '对比期', value: 34896 },
{ date: '2020-07-06', index: '权益领取用户数', type: '对比期', value: 28896 },
{ date: '2020-07-06', index: '引导IUV', type: '对比期', value: 36896 },
{ date: '2020-07-06', index: '引导成交用户数', type: '对比期', value: 34896 },
];

function processData(rawData) {
const res = [];
[rawData.filter(({ type }) => type === '本期'), rawData.filter(({ type }) => type === '对比期')].forEach((data) => {
const len = data.length - 1;
for (let idx = 0; idx < data.length; idx += 1) {
const prevVal = data[idx === 0 ? 0 : idx - 1].value;
const nextVal = data[idx === len ? len : idx + 1].value;
const { date, index, value, type } = data[idx];
res.push({
index,
value,
type,
date,
flag: 'transformed',
});
const incFlag = value < nextVal;
res.push({
index,
type,
date,
value: Math.max(prevVal - value, 0),
flag: incFlag ? 'increased' : 'non-transformed',
rate: incFlag ? (nextVal - value) / value : nextVal / value,
});
}
});
return res;
}

function getRectPath(points) {
const path = [];
for (let i = 0; i < points.length; i++) {
const point = points[i];
if (point) {
const action = i === 0 ? 'M' : 'L';
path.push([action, point.x, point.y]);
}
}

const first = points[0];
path.push(['L', first.x, first.y]);
path.push(['z']);
return path;
}

function getFillAttrs(cfg) {
const defaultAttrs = {
lineWidth: 0,
fill: '#1890FF',
fillOpacity: 0.85,
};

return {
...defaultAttrs,
...cfg.style,
fill: cfg.color,
stroke: cfg.color,
fillOpacity: cfg.opacity,
};
}

// 自定义 Shape
G2.registerShape('interval', 'contrast-funnel', {
draw(cfg, container) {
const attrs = getFillAttrs(cfg);
let rectPath = getRectPath(cfg.points);
rectPath = this.parsePath(rectPath);

const group = container.addGroup();
group.addShape('path', {
attrs: {
...attrs,
path: rectPath,
},
});
const { flag } = cfg.data;
if (cfg.nextPoints && flag !== 'transformed') {
let linkPath = [
['M', cfg.points[2].x, cfg.points[3].y],
['L', cfg.nextPoints[0].x, cfg.nextPoints[0].y],
];

if (cfg.nextPoints[0].y === 0) {
linkPath[1] = ['L', cfg.nextPoints[1].x, cfg.nextPoints[1].y];
}
linkPath = this.parsePath(linkPath);

const [[, x1, y1], [, x2, y2]] = linkPath;
group.addShape('path', {
attrs: {
path: linkPath,
stroke: '#c5d0d9',
},
});
const text = group.addShape('text', {
attrs: {
x: (x1 + x2) / 2,
y: (y1 + y2) / 2,
text: `${{ 'non-transformed': '▼转化率', increased: '▲增长率' }[flag]}${(cfg.data.rate * 100).toFixed(0)}%`,
fill: { 'non-transformed': '#009f86', increased: '#ff4737' }[flag],
textAlign: 'center',
textBaseline: 'middle',
fontSize: 14,
},
zIndex: 2,
});
const { x, y, width, height } = text.getBBox();
group.addShape('rect', {
attrs: {
x,
y,
width,
height,
fill: 'white',
},
zIndex: 1,
});
text.toFront();
}
return group;
},
});

const defaultOptions = {};

function adaptor(params) {
const { chart, options } = params;
const { data, theme } = options;

chart.data(data);
chart.legend(false);
chart.theme(deepMix({}, theme || G2.getTheme(theme)));
chart.scale('value', { nice: true });

chart.facet('mirror', {
fields: ['type'],
spacing: ['12%', 0],
transpose: true,
showTitle: false,
eachView: (view, facet) => {
const idx = facet.columnIndex;
// 关闭所有 axis
view.axis(false);
view.legend({
custom: true,
position: ['top-right', 'top-left'][idx],
items: [
{
name: name[idx],
marker: {
symbol: 'hyphen',
style: {
stroke: columnColor.map((c) => c.transformed)[idx],
},
},
},
],
});
view
.coordinate()
.transpose()
.scale(...(idx === 0 ? [-1, -1] : [1, -1]));
view
.interval()
.adjust('stack')
.position('index*value')
.color('index*flag', (index, flag) => columnColor[idx][flag])
.label('value*flag', (value, flag) => {
if (flag !== 'transformed') return { content: '' };
return {
position: 'left',
content: value.toLocaleString(),
style: {
textAlign: ['end', 'start'][idx],
fill: '#fff',
shadowColor: '#212121',
shadowBlur: 5,
},
};
})
.shape('contrast-funnel');
},
});

chart.tooltip({
shared: true,
title: (item) => {
return `${item}`;
},
customItems: ([currSurplus, currLoss, compareSurplus, compareLoss]) => {
const [currColor, completeColor] = columnColor;
const [n1, n2, n3, n4] = tooltipItemsName;
return [
{
marker: true,
color: currColor.transformed,
name: `${n1}(${currSurplus.data.date})`,
value: Number(currSurplus.value).toLocaleString(),
},
{
marker: true,
color: currColor['non-transformed'],
name: `${n2}(${currLoss.data.date})`,
value: Number(currLoss.value).toLocaleString(),
},
{
marker: true,
color: completeColor.transformed,
name: `${n3}(${compareSurplus.data.date})`,
value: Number(compareSurplus.value).toLocaleString(),
},
{
marker: true,
color: completeColor['non-transformed'],
name: `${n4}(${compareLoss.data.date})`,
value: Number(compareLoss.value).toLocaleString(),
},
];
},
});

rawData
.filter(({ type }) => type === '本期')
.forEach(({ index }, idx) => {
chart.annotation().text({
content: index,
style: { textAlign: 'center', textBaseline: 'middle' },
position: () => {
const { y: cY, height: cHeight } = chart.coordinateBBox;
const { y: vY, height: vHeight } = chart.views[0].coordinateBBox;
const yScale = chart.views[0].getScaleByField('index');
return ['50%', `${((vY - cY + vHeight * yScale.scale(index)) / cHeight) * 100}%`];
},
});
});

chart.removeInteraction('legend-filter'); // 移除图例过滤交互
}

const funnel = new P('container', {}, adaptor, { data: processData(rawData) });

funnel.render();
10 changes: 9 additions & 1 deletion examples/case/statistical-scenario/demo/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
"en": "Category"
},
"demos": [
{
"filename": "compare-funnel.ts",
"title": {
"zh": "对比漏斗图",
"en": "Compare Funnel Diagram"
},
"new": true,
"screenshot": "https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*gS12TpN1MN8AAAAAAAAAAAAAARQnAQ"
},
{
"filename": "trend.jsx",
"title": {
Expand Down Expand Up @@ -36,7 +45,6 @@
"en": "Statistical Charts-Pie"
},
"screenshot": "https://gw.alipayobjects.com/mdn/rms_d314dd/afts/img/A*OOnhQI4Sme4AAAAAAAAAAAAAARQnAQ"

},
{
"filename": "trend-funnel.ts",
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
},
"dependencies": {
"@antv/event-emitter": "^0.1.2",
"@antv/g2": "^4.1.23",
"@antv/g2": "^4.1.26",
"d3-hierarchy": "^2.0.0",
"d3-regression": "^1.3.5",
"fmin": "^0.0.2",
Expand Down Expand Up @@ -159,4 +159,4 @@
"@babel/standalone": "7.12.6",
"d3-array": "2.12.1"
}
}
}