-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
animated-arc-group-layer.ts
80 lines (70 loc) · 2.21 KB
/
animated-arc-group-layer.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
import {CompositeLayer, UpdateParameters} from '@deck.gl/core';
import AnimatedArcLayer, {AnimatedArcLayerProps} from './animated-arc-layer';
const MAX_ARCS_PER_LAYER = 2500;
type ArcsGroup<DataT> = {
startTime: number;
endTime: number;
data: DataT[];
};
/** Same effect as the AnimatedArcLayer, but perf optimized.
* Data is divided into smaller groups, and one sub layer is rendered for each group.
* This allows us to cheaply cull invisible arcs by turning layers off and on.
*/
export default class AnimatedArcGroupLayer<DataT = any, ExtraProps = {}> extends CompositeLayer<
ExtraProps & Required<AnimatedArcLayerProps<DataT>>
> {
layerName = 'AnimatedArcGroupLayer';
defaultProps = AnimatedArcLayer.defaultProps;
state!: {
groups: ArcsGroup<DataT>[];
};
updateState({props, changeFlags}: UpdateParameters<this>) {
if (changeFlags.dataChanged) {
// Sort and group data
const {data, getSourceTimestamp, getTargetTimestamp} = props;
// @ts-ignore
const groups = sortAndGroup(data, getSourceTimestamp, getTargetTimestamp);
this.setState({groups});
}
}
renderLayers() {
const {timeRange} = this.props;
const {groups = []} = this.state;
return groups.map(
(group, index) =>
new AnimatedArcLayer(
this.props,
this.getSubLayerProps({
id: index.toString(),
data: group.data,
visible: group.startTime < timeRange[1] && group.endTime > timeRange[0],
timeRange
})
)
);
}
}
function sortAndGroup<DataT>(
data: DataT[],
getStartTime: (d: DataT) => number,
getEndTime: (d: DataT) => number,
groupSize: number = MAX_ARCS_PER_LAYER
): ArcsGroup<DataT>[] {
const groups: ArcsGroup<DataT>[] = [];
let group: ArcsGroup<DataT>;
data.sort((d1, d2) => getStartTime(d1) - getStartTime(d2));
for (const d of data) {
if (!group || group.data.length >= groupSize) {
group = {
startTime: Infinity,
endTime: -Infinity,
data: []
};
groups.push(group);
}
group.data.push(d);
group.startTime = Math.min(group.startTime, getStartTime(d));
group.endTime = Math.max(group.endTime, getEndTime(d));
}
return groups;
}