@deck.gl/geo-layers
Version:
deck.gl layers supporting geospatial use cases and GIS formats
282 lines (251 loc) • 6.15 kB
JavaScript
import { CompositeLayer, _flatten as flatten } from '@deck.gl/core';
import { GeoJsonLayer } from '@deck.gl/layers';
import Tileset2D, { STRATEGY_DEFAULT } from './tileset-2d';
import { urlType, getURLFromTemplate } from './utils';
const defaultProps = {
data: [],
dataComparator: urlType.equals,
renderSubLayers: {
type: 'function',
value: props => new GeoJsonLayer(props),
compare: false
},
getTileData: {
type: 'function',
optional: true,
value: null,
compare: false
},
onViewportLoad: {
type: 'function',
optional: true,
value: null,
compare: false
},
onTileLoad: {
type: 'function',
value: tile => {},
compare: false
},
onTileUnload: {
type: 'function',
value: tile => {},
compare: false
},
onTileError: {
type: 'function',
value: err => console.error(err),
compare: false
},
extent: {
type: 'array',
optional: true,
value: null,
compare: true
},
tileSize: 512,
maxZoom: null,
minZoom: 0,
maxCacheSize: null,
maxCacheByteSize: null,
refinementStrategy: STRATEGY_DEFAULT,
zRange: null,
maxRequests: 6,
zoomOffset: 0
};
export default class TileLayer extends CompositeLayer {
initializeState() {
this.state = {
tileset: null,
isLoaded: false
};
}
finalizeState() {
var _this$state$tileset;
(_this$state$tileset = this.state.tileset) === null || _this$state$tileset === void 0 ? void 0 : _this$state$tileset.finalize();
}
get isLoaded() {
const {
tileset
} = this.state;
return tileset.selectedTiles.every(tile => tile.isLoaded && tile.layers && tile.layers.every(layer => layer.isLoaded));
}
shouldUpdateState({
changeFlags
}) {
return changeFlags.somethingChanged;
}
updateState({
props,
changeFlags
}) {
let {
tileset
} = this.state;
const propsChanged = changeFlags.propsOrDataChanged || changeFlags.updateTriggersChanged;
const dataChanged = changeFlags.dataChanged || changeFlags.updateTriggersChanged && (changeFlags.updateTriggersChanged.all || changeFlags.updateTriggersChanged.getTileData);
if (!tileset) {
tileset = new Tileset2D(this._getTilesetOptions(props));
this.setState({
tileset
});
} else if (propsChanged) {
tileset.setOptions(this._getTilesetOptions(props));
if (dataChanged) {
tileset.reloadAll();
} else {
this.state.tileset.tiles.forEach(tile => {
tile.layers = null;
});
}
}
this._updateTileset();
}
_getTilesetOptions(props) {
const {
tileSize,
maxCacheSize,
maxCacheByteSize,
refinementStrategy,
extent,
maxZoom,
minZoom,
maxRequests,
zoomOffset
} = props;
return {
maxCacheSize,
maxCacheByteSize,
maxZoom,
minZoom,
tileSize,
refinementStrategy,
extent,
maxRequests,
zoomOffset,
getTileData: this.getTileData.bind(this),
onTileLoad: this._onTileLoad.bind(this),
onTileError: this._onTileError.bind(this),
onTileUnload: this._onTileUnload.bind(this)
};
}
_updateTileset() {
const {
tileset
} = this.state;
const {
zRange,
modelMatrix
} = this.props;
const frameNumber = tileset.update(this.context.viewport, {
zRange,
modelMatrix
});
const {
isLoaded
} = tileset;
const loadingStateChanged = this.state.isLoaded !== isLoaded;
const tilesetChanged = this.state.frameNumber !== frameNumber;
if (isLoaded && (loadingStateChanged || tilesetChanged)) {
this._onViewportLoad();
}
if (tilesetChanged) {
this.setState({
frameNumber
});
}
this.state.isLoaded = isLoaded;
}
_onViewportLoad() {
const {
tileset
} = this.state;
const {
onViewportLoad
} = this.props;
if (onViewportLoad) {
onViewportLoad(tileset.selectedTiles);
}
}
_onTileLoad(tile) {
this.props.onTileLoad(tile);
tile.layers = null;
this.setNeedsUpdate();
}
_onTileError(error, tile) {
this.props.onTileError(error);
tile.layers = null;
this.setNeedsUpdate();
}
_onTileUnload(tile) {
this.props.onTileUnload(tile);
}
getTileData(tile) {
const {
data,
getTileData,
fetch
} = this.props;
const {
signal
} = tile;
tile.url = getURLFromTemplate(data, tile);
if (getTileData) {
return getTileData(tile);
}
if (tile.url) {
return fetch(tile.url, {
propName: 'data',
layer: this,
signal
});
}
return null;
}
renderSubLayers(props) {
return this.props.renderSubLayers(props);
}
getSubLayerPropsByTile(tile) {
return null;
}
getPickingInfo({
info,
sourceLayer
}) {
info.tile = sourceLayer.props.tile;
return info;
}
_updateAutoHighlight(info) {
if (info.sourceLayer) {
info.sourceLayer.updateAutoHighlight(info);
}
}
renderLayers() {
return this.state.tileset.tiles.map(tile => {
const subLayerProps = this.getSubLayerPropsByTile(tile);
if (!tile.isLoaded && !tile.content) {} else if (!tile.layers) {
const layers = this.renderSubLayers({ ...this.props,
id: "".concat(this.id, "-").concat(tile.x, "-").concat(tile.y, "-").concat(tile.z),
data: tile.content,
_offset: 0,
tile
});
tile.layers = flatten(layers, Boolean).map(layer => layer.clone({
tile,
...subLayerProps
}));
} else if (subLayerProps && tile.layers[0] && Object.keys(subLayerProps).some(propName => tile.layers[0].props[propName] !== subLayerProps[propName])) {
tile.layers = tile.layers.map(layer => layer.clone(subLayerProps));
}
return tile.layers;
});
}
filterSubLayer({
layer
}) {
return layer.props.tile.isVisible;
}
}
TileLayer.layerName = 'TileLayer';
TileLayer.defaultProps = defaultProps;
//# sourceMappingURL=tile-layer.js.map