UNPKG

4.61 kBPlain TextView Raw
1import browser from '../util/browser';
2
3import {Placement} from '../symbol/placement';
4
5import type Transform from '../geo/transform';
6import type StyleLayer from './style_layer';
7import type SymbolStyleLayer from './style_layer/symbol_style_layer';
8import type Tile from '../source/tile';
9import type {BucketPart} from '../symbol/placement';
10
11class LayerPlacement {
12 _sortAcrossTiles: boolean;
13 _currentTileIndex: number;
14 _currentPartIndex: number;
15 _seenCrossTileIDs: {
16 [k in string | number]: boolean;
17 };
18 _bucketParts: Array<BucketPart>;
19
20 constructor(styleLayer: SymbolStyleLayer) {
21 this._sortAcrossTiles = styleLayer.layout.get('symbol-z-order') !== 'viewport-y' &&
22 !styleLayer.layout.get('symbol-sort-key').isConstant();
23
24 this._currentTileIndex = 0;
25 this._currentPartIndex = 0;
26 this._seenCrossTileIDs = {};
27 this._bucketParts = [];
28 }
29
30 continuePlacement(tiles: Array<Tile>, placement: Placement, showCollisionBoxes: boolean, styleLayer: StyleLayer, shouldPausePlacement: () => boolean) {
31
32 const bucketParts = this._bucketParts;
33
34 while (this._currentTileIndex < tiles.length) {
35 const tile = tiles[this._currentTileIndex];
36 placement.getBucketParts(bucketParts, styleLayer, tile, this._sortAcrossTiles);
37
38 this._currentTileIndex++;
39 if (shouldPausePlacement()) {
40 return true;
41 }
42 }
43
44 if (this._sortAcrossTiles) {
45 this._sortAcrossTiles = false;
46 bucketParts.sort((a, b) => (a.sortKey as any as number) - (b.sortKey as any as number));
47 }
48
49 while (this._currentPartIndex < bucketParts.length) {
50 const bucketPart = bucketParts[this._currentPartIndex];
51 placement.placeLayerBucketPart(bucketPart, this._seenCrossTileIDs, showCollisionBoxes);
52
53 this._currentPartIndex++;
54 if (shouldPausePlacement()) {
55 return true;
56 }
57 }
58 return false;
59 }
60}
61
62class PauseablePlacement {
63 placement: Placement;
64 _done: boolean;
65 _currentPlacementIndex: number;
66 _forceFullPlacement: boolean;
67 _showCollisionBoxes: boolean;
68 _inProgressLayer: LayerPlacement;
69
70 constructor(
71 transform: Transform,
72 order: Array<string>,
73 forceFullPlacement: boolean,
74 showCollisionBoxes: boolean,
75 fadeDuration: number,
76 crossSourceCollisions: boolean,
77 prevPlacement?: Placement
78 ) {
79 this.placement = new Placement(transform, fadeDuration, crossSourceCollisions, prevPlacement);
80 this._currentPlacementIndex = order.length - 1;
81 this._forceFullPlacement = forceFullPlacement;
82 this._showCollisionBoxes = showCollisionBoxes;
83 this._done = false;
84 }
85
86 isDone() {
87 return this._done;
88 }
89
90 continuePlacement(
91 order: Array<string>,
92 layers: {[_: string]: StyleLayer},
93 layerTiles: {[_: string]: Array<Tile>}
94 ) {
95 const startTime = browser.now();
96
97 const shouldPausePlacement = () => {
98 const elapsedTime = browser.now() - startTime;
99 return this._forceFullPlacement ? false : elapsedTime > 2;
100 };
101
102 while (this._currentPlacementIndex >= 0) {
103 const layerId = order[this._currentPlacementIndex];
104 const layer = layers[layerId];
105 const placementZoom = this.placement.collisionIndex.transform.zoom;
106 if (layer.type === 'symbol' &&
107 (!layer.minzoom || layer.minzoom <= placementZoom) &&
108 (!layer.maxzoom || layer.maxzoom > placementZoom)) {
109
110 if (!this._inProgressLayer) {
111 this._inProgressLayer = new LayerPlacement(layer as any as SymbolStyleLayer);
112 }
113
114 const pausePlacement = this._inProgressLayer.continuePlacement(layerTiles[layer.source], this.placement, this._showCollisionBoxes, layer, shouldPausePlacement);
115
116 if (pausePlacement) {
117 // We didn't finish placing all layers within 2ms,
118 // but we can keep rendering with a partial placement
119 // We'll resume here on the next frame
120 return;
121 }
122
123 delete this._inProgressLayer;
124 }
125
126 this._currentPlacementIndex--;
127 }
128
129 this._done = true;
130 }
131
132 commit(now: number) {
133 this.placement.commit(now);
134 return this.placement;
135 }
136}
137
138export default PauseablePlacement;