-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilter.ts
118 lines (105 loc) · 2.83 KB
/
filter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { deepMix } from '@antv/util';
import { G2Mark, TransformComponent as TC } from '../runtime';
import { FilterTransform } from '../spec';
import { defined } from '../utils/helper';
import { columnOf } from './utils/helper';
export type FilterOptions = Omit<FilterTransform, 'type'>;
function normalizeValue(value) {
if (typeof value === 'object') return [value.value, value.ordinal];
else return [value, true];
}
function filterWhenNoElements(mark: G2Mark) {
const { encode } = mark;
// keep y-axis
const noElementMark = {
...mark,
encode: {
...mark.encode,
y: {
...mark.encode.y,
value: [],
},
},
};
const targetField = encode?.color?.field;
if (!encode || !targetField) {
return noElementMark;
}
// 获取color的筛选源
let filterObject;
for (const [key, v] of Object.entries(encode)) {
if ((key === 'x' || key === 'y') && v.field === targetField) {
filterObject = {
...filterObject,
[key]: {
...v,
value: [],
},
};
}
}
if (!filterObject) {
return noElementMark;
}
return {
...mark,
encode: {
...mark.encode,
...filterObject,
},
};
}
/**
* The Filter transform filter channels.
*/
export const Filter: TC<FilterOptions> = (options = {}) => {
return (I, mark) => {
const { encode, data } = mark;
const filters = Object.entries(options)
.map(([key, v]) => {
const [V] = columnOf(encode, key);
// Skip empty channel.
if (!V) return null;
const [value, ordinal = true] = normalizeValue(v);
if (typeof value === 'function') return (i) => value(V[i]);
if (ordinal) {
const expectedValues = Array.isArray(value) ? value : [value];
// Skip empty expected values.
if (expectedValues.length === 0) return null;
return (i) => expectedValues.includes(V[i]);
} else {
const [start, end] = value;
return (i) => V[i] >= start && V[i] <= end;
}
})
.filter(defined);
// Filter index and channels.
const totalFilter = (i) => filters.every((f) => f(i));
const FI = I.filter(totalFilter);
const newIndex = FI.map((_, i) => i);
if (filters.length === 0) {
const targetMark = filterWhenNoElements(mark);
return [I, targetMark];
}
const newEncodes = Object.entries(encode).map(([key, encode]) => {
return [
key,
{
...encode,
value: newIndex
.map((i) => encode.value[FI[i]])
.filter((v) => v !== undefined),
},
];
});
return [
newIndex,
deepMix({}, mark, {
encode: Object.fromEntries(newEncodes),
// Filter data for tooltip item.
data: FI.map((i) => data[i]),
}),
];
};
};
Filter.props = {};