Skip to content

Commit b7923d7

Browse files
committed
fix(funnel): 对比漏斗图更改
1 parent 2eb60eb commit b7923d7

File tree

5 files changed

+87
-55
lines changed

5 files changed

+87
-55
lines changed

__tests__/unit/plots/funnel/compare-spec.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,17 @@ describe('compare funnel', () => {
6767
'2020Q1': PV_DATA_COMPARE.filter((item) => item.quarter === '2020Q1'),
6868
'2020Q2': PV_DATA_COMPARE.filter((item) => item.quarter === '2020Q2'),
6969
};
70+
const max = {
71+
'2020Q1': maxBy(origin['2020Q1'], 'pv').pv,
72+
'2020Q2': maxBy(origin['2020Q2'], 'pv').pv,
73+
};
7074

71-
const max = maxBy(PV_DATA_COMPARE, 'pv').pv;
75+
const { data } = funnelView.getOptions();
7276

73-
const { data } = funnel.chart.getOptions();
7477
data.forEach((item) => {
7578
const originData = origin[item.quarter];
7679
const originIndex = originData.findIndex((jtem) => jtem.pv === item.pv);
77-
const percent = item.pv / max;
80+
const percent = item.pv / max[item.quarter];
7881
expect(item[FUNNEL_PERCENT]).toEqual(percent);
7982
expect(item[FUNNEL_MAPPING_VALUE]).toEqual(0.5 * percent + 0.3);
8083
expect(item[FUNNEL_CONVERSATION]).toEqual([get(originData, [originIndex - 1, 'pv']), item.pv]);

src/plots/funnel/adaptor.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ function legend(params: Params<FunnelOptions>): Params<FunnelOptions> {
146146
export function interaction<O extends Pick<FunnelOptions, 'interactions'>>(params: Params<O>): Params<O> {
147147
const { chart, options } = params;
148148
// @ts-ignore
149-
const { interactions, dynamicHeight, compareField } = options;
149+
const { interactions, dynamicHeight } = options;
150150

151151
each(interactions, (i: Interaction) => {
152152
if (i.enable === false) {
@@ -156,7 +156,7 @@ export function interaction<O extends Pick<FunnelOptions, 'interactions'>>(param
156156
}
157157
});
158158
// 动态高度 不进行交互操作
159-
if (!dynamicHeight && !compareField) {
159+
if (!dynamicHeight) {
160160
chart.interaction(FUNNEL_LEGEND_FILTER, {
161161
start: [{ ...interactionStart, arg: options }],
162162
});

src/plots/funnel/geometries/common.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { FUNNEL_PERCENT, FUNNEL_CONVERSATION, FUNNEL_MAPPING_VALUE } from '../co
55
import { Params } from '../../../core/adaptor';
66
import { FunnelOptions } from '../types';
77

8+
export const CONVERSION_TAG_NAME = 'CONVERSION_TAG_NAME';
9+
810
/**
911
* 漏斗图 transform
1012
* @param geometry
@@ -50,14 +52,14 @@ export function conversionTagComponent(
5052
// @ts-ignore
5153
const { conversionTag, filteredData } = options;
5254

53-
let { data } = chart.getOptions();
54-
data = filteredData || data;
55+
const data = filteredData || chart.getOptions().data;
5556
if (conversionTag) {
5657
const { formatter } = conversionTag;
5758
data.forEach((obj, index) => {
5859
if (index <= 0 || Number.isNaN(obj[FUNNEL_MAPPING_VALUE])) return;
5960
const lineOption = getLineCoordinate(obj, index, data, {
6061
top: true,
62+
name: CONVERSION_TAG_NAME,
6163
text: {
6264
content: isFunction(formatter) ? formatter(obj, data) : formatter,
6365
offsetX: conversionTag.offsetX,

src/plots/funnel/geometries/compare.ts

+50-41
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Types } from '@antv/g2';
2-
import { isArray } from '@antv/util';
2+
import { isArray, isNumber, get, map } from '@antv/util';
33
import { flow, deepAssign } from '../../../utils';
44
import { Params } from '../../../core/adaptor';
55
import { Datum, Data } from '../../../types/common';
@@ -114,52 +114,61 @@ function geometry(params: Params<FunnelOptions>): Params<FunnelOptions> {
114114
return params;
115115
}
116116

117+
export function compareConversionTag(params: Params<FunnelOptions>) {
118+
// @ts-ignore
119+
const { chart, index, options } = params;
120+
const { conversionTag, isTransposed } = options;
121+
(isNumber(index) ? [chart] : chart.views).forEach((view, viewIndex) => {
122+
// 获取形状位置,再转化为需要的转化率位置
123+
const dataArray = get(view, ['geometries', '0', 'dataArray'], []);
124+
const size = get(view, ['options', 'data', 'length']);
125+
const x = map(dataArray, (item) => get(item, ['0', 'nextPoints', '0', 'x']) * size - 0.5);
126+
127+
const getLineCoordinate = (
128+
datum: Datum,
129+
datumIndex: number,
130+
data: Data,
131+
initLineOption: Record<string, any>
132+
): Types.LineOption => {
133+
const ratio = (index || viewIndex) === 0 ? -1 : 1;
134+
return deepAssign({}, initLineOption, {
135+
start: [x[datumIndex - 1] || datumIndex - 0.5, datum[FUNNEL_MAPPING_VALUE]],
136+
end: [x[datumIndex - 1] || datumIndex - 0.5, datum[FUNNEL_MAPPING_VALUE] + 0.05],
137+
text: isTransposed
138+
? {
139+
style: {
140+
textAlign: 'start',
141+
},
142+
}
143+
: {
144+
offsetX: conversionTag !== false ? ratio * conversionTag.offsetX : 0,
145+
style: {
146+
textAlign: (index || viewIndex) === 0 ? 'end' : 'start',
147+
},
148+
},
149+
});
150+
};
151+
152+
conversionTagComponent(getLineCoordinate)(
153+
deepAssign(
154+
{},
155+
{
156+
chart: view,
157+
options,
158+
}
159+
)
160+
);
161+
});
162+
}
163+
117164
/**
118165
* 转化率组件
119166
* @param params
120167
*/
121168
function conversionTag(params: Params<FunnelOptions>): Params<FunnelOptions> {
122-
const { chart, options } = params;
123-
const { conversionTag, isTransposed } = options;
169+
const { chart } = params;
124170
// @ts-ignore
125-
chart.once('beforepaint', () => {
126-
chart.views.forEach((view, viewIndex) => {
127-
const getLineCoordinate = (
128-
datum: Datum,
129-
datumIndex: number,
130-
data: Data,
131-
initLineOption: Record<string, any>
132-
): Types.LineOption => {
133-
const ratio = viewIndex === 0 ? -1 : 1;
134-
return deepAssign({}, initLineOption, {
135-
start: [datumIndex - 0.5, datum[FUNNEL_MAPPING_VALUE]],
136-
end: [datumIndex - 0.5, datum[FUNNEL_MAPPING_VALUE] + 0.05],
137-
text: isTransposed
138-
? {
139-
style: {
140-
textAlign: 'start',
141-
},
142-
}
143-
: {
144-
offsetX: conversionTag !== false ? ratio * conversionTag.offsetX : 0,
145-
style: {
146-
textAlign: viewIndex === 0 ? 'end' : 'start',
147-
},
148-
},
149-
});
150-
};
151-
152-
conversionTagComponent(getLineCoordinate)(
153-
deepAssign(
154-
{},
155-
{
156-
chart: view,
157-
options,
158-
}
159-
)
160-
);
161-
});
162-
});
171+
chart.once('beforepaint', () => compareConversionTag(params));
163172
return params;
164173
}
165174

src/plots/funnel/interactions/funnel-conversion-tag.ts

+25-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { get, map } from '@antv/util';
1+
import { get, map, filter, each } from '@antv/util';
22
import { Action } from '@antv/g2';
3-
import { conversionTag } from '../geometries/basic';
4-
import { transformData } from '../geometries/common';
3+
import { conversionTag as basicConversionTag } from '../geometries/basic';
4+
import { compareConversionTag } from '../geometries/compare';
5+
import { transformData, CONVERSION_TAG_NAME } from '../geometries/common';
56
import { FunnelOptions } from '../types';
67

78
/**
@@ -12,16 +13,33 @@ export class ConversionTagAction extends Action {
1213
public change(options: FunnelOptions) {
1314
// 防止多次重复渲染
1415
if (!this.rendering) {
15-
const { seriesField } = options;
16+
const { seriesField, compareField } = options;
17+
const conversionTag = compareField ? compareConversionTag : basicConversionTag;
1618
const { view } = this.context;
1719
// 兼容分面漏斗图
18-
const views = seriesField ? view.views : [view];
19-
map(views, (v) => {
20-
v.getController('annotation').clear(true);
20+
const views = seriesField || compareField ? view.views : [view];
21+
map(views, (v, index) => {
22+
// 防止影响其他 annotations 被去除
23+
const annotationController = v.getController('annotation');
24+
25+
const annotations = filter(
26+
get(annotationController, ['option'], []),
27+
({ name }) => name !== CONVERSION_TAG_NAME
28+
);
29+
30+
annotationController.clear(true);
31+
32+
each(annotations, (annotation) => {
33+
if (typeof annotation === 'object') {
34+
v.annotation()[annotation.type](annotation);
35+
}
36+
});
37+
2138
const data = get(v, ['filteredData'], v.getOptions().data);
2239

2340
conversionTag({
2441
chart: v,
42+
index,
2543
options: {
2644
...options,
2745
// @ts-ignore

0 commit comments

Comments
 (0)