package.src.style.pauseable_placement.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mapbox-gl Show documentation
Show all versions of mapbox-gl Show documentation
A WebGL interactive maps library
The newest version!
// @flow
import browser from '../util/browser';
import {Placement} from '../symbol/placement';
import type Transform from '../geo/transform';
import type StyleLayer from './style_layer';
import type SymbolStyleLayer from './style_layer/symbol_style_layer';
import type Tile from '../source/tile';
import type {BucketPart} from '../symbol/placement';
class LayerPlacement {
_sortAcrossTiles: boolean;
_currentTileIndex: number;
_currentPartIndex: number;
_seenCrossTileIDs: { [string | number]: boolean };
_bucketParts: Array;
constructor(styleLayer: SymbolStyleLayer) {
this._sortAcrossTiles = styleLayer.layout.get('symbol-z-order') !== 'viewport-y' &&
styleLayer.layout.get('symbol-sort-key').constantOr(1) !== undefined;
this._currentTileIndex = 0;
this._currentPartIndex = 0;
this._seenCrossTileIDs = {};
this._bucketParts = [];
}
continuePlacement(tiles: Array, placement: Placement, showCollisionBoxes: boolean, styleLayer: StyleLayer, shouldPausePlacement: () => boolean) {
const bucketParts = this._bucketParts;
while (this._currentTileIndex < tiles.length) {
const tile = tiles[this._currentTileIndex];
placement.getBucketParts(bucketParts, styleLayer, tile, this._sortAcrossTiles);
this._currentTileIndex++;
if (shouldPausePlacement()) {
return true;
}
}
if (this._sortAcrossTiles) {
this._sortAcrossTiles = false;
bucketParts.sort((a, b) => ((a.sortKey: any): number) - ((b.sortKey: any): number));
}
while (this._currentPartIndex < bucketParts.length) {
const bucketPart = bucketParts[this._currentPartIndex];
placement.placeLayerBucketPart(bucketPart, this._seenCrossTileIDs, showCollisionBoxes);
this._currentPartIndex++;
if (shouldPausePlacement()) {
return true;
}
}
return false;
}
}
class PauseablePlacement {
placement: Placement;
_done: boolean;
_currentPlacementIndex: number;
_forceFullPlacement: boolean;
_showCollisionBoxes: boolean;
_inProgressLayer: ?LayerPlacement;
constructor(transform: Transform, order: Array,
forceFullPlacement: boolean,
showCollisionBoxes: boolean,
fadeDuration: number,
crossSourceCollisions: boolean,
prevPlacement?: Placement) {
this.placement = new Placement(transform, fadeDuration, crossSourceCollisions, prevPlacement);
this._currentPlacementIndex = order.length - 1;
this._forceFullPlacement = forceFullPlacement;
this._showCollisionBoxes = showCollisionBoxes;
this._done = false;
}
isDone(): boolean {
return this._done;
}
continuePlacement(order: Array, layers: {[_: string]: StyleLayer}, layerTiles: {[_: string]: Array}) {
const startTime = browser.now();
const shouldPausePlacement = () => {
const elapsedTime = browser.now() - startTime;
return this._forceFullPlacement ? false : elapsedTime > 2;
};
while (this._currentPlacementIndex >= 0) {
const layerId = order[this._currentPlacementIndex];
const layer = layers[layerId];
const placementZoom = this.placement.collisionIndex.transform.zoom;
if (layer.type === 'symbol' &&
(!layer.minzoom || layer.minzoom <= placementZoom) &&
(!layer.maxzoom || layer.maxzoom > placementZoom)) {
if (!this._inProgressLayer) {
this._inProgressLayer = new LayerPlacement(((layer: any): SymbolStyleLayer));
}
const pausePlacement = this._inProgressLayer.continuePlacement(layerTiles[layer.source], this.placement, this._showCollisionBoxes, layer, shouldPausePlacement);
if (pausePlacement) {
// We didn't finish placing all layers within 2ms,
// but we can keep rendering with a partial placement
// We'll resume here on the next frame
return;
}
delete this._inProgressLayer;
}
this._currentPlacementIndex--;
}
this._done = true;
}
commit(now: number) {
this.placement.commit(now);
return this.placement;
}
}
export default PauseablePlacement;