@deck.gl/carto
Version:
CARTO official integration with Deck.gl. Build geospatial applications using CARTO and Deck.gl.
104 lines (85 loc) • 3.37 kB
text/typescript
// deck.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
import {registerLoaders} from '@loaders.gl/core';
import {DefaultProps, LayerProps} from '@deck.gl/core';
import CartoSpatialTileLoader from './schema/carto-spatial-tile-loader';
registerLoaders([CartoSpatialTileLoader]);
import {PickingInfo} from '@deck.gl/core';
import {TileLayer, _Tile2DHeader as Tile2DHeader, TileLayerProps} from '@deck.gl/geo-layers';
import {DEFAULT_TILE_SIZE} from '../constants';
function isFeatureIdDefined(value: unknown): boolean {
return value !== undefined && value !== null && value !== '';
}
const defaultProps: DefaultProps<SpatialIndexTileLayerProps> = {
tileSize: DEFAULT_TILE_SIZE
};
/** All properties supported by SpatialIndexTileLayer. */
export type SpatialIndexTileLayerProps<DataT = unknown> = _SpatialIndexTileLayerProps &
TileLayerProps<DataT>;
/** Properties added by SpatialIndexTileLayer. */
type _SpatialIndexTileLayerProps = {};
export default class SpatialIndexTileLayer<
DataT = any,
ExtraProps extends {} = {}
> extends TileLayer<DataT, ExtraProps & Required<_SpatialIndexTileLayerProps>> {
static layerName = 'SpatialIndexTileLayer';
static defaultProps = defaultProps;
state!: TileLayer<DataT>['state'] & {
hoveredFeatureId: BigInt | number | null;
highlightColor: number[];
};
protected _updateAutoHighlight(info: PickingInfo): void {
const {hoveredFeatureId} = this.state;
const hoveredFeature = info.object;
let newHoveredFeatureId: BigInt | number | null = null;
if (hoveredFeature) {
newHoveredFeatureId = hoveredFeature.id;
}
if (hoveredFeatureId !== newHoveredFeatureId) {
let {highlightColor} = this.props;
if (typeof highlightColor === 'function') {
highlightColor = highlightColor(info);
}
this.setState({
highlightColor,
hoveredFeatureId: newHoveredFeatureId
});
}
}
getSubLayerPropsByTile(tile: Tile2DHeader): Partial<LayerProps> | null {
return {
highlightedObjectIndex: this.getHighlightedObjectIndex(tile),
highlightColor: this.state.highlightColor
};
}
getHighlightedObjectIndex(tile: Tile2DHeader) {
const {hoveredFeatureId} = this.state;
const data = tile.content;
const isFeatureIdPresent = isFeatureIdDefined(hoveredFeatureId);
if (
!isFeatureIdPresent ||
!Array.isArray(data) ||
// Quick check for whether id is within tile. data.findIndex is expensive
!this._featureInTile(tile, hoveredFeatureId!)
) {
return -1;
}
return data.findIndex(feature => feature.id === hoveredFeatureId);
}
_featureInTile(tile: Tile2DHeader, featureId: BigInt | number) {
// TODO: Tile2DHeader index should be generic for H3TileIndex or QuadbinTileIndex
const tileset = this.state.tileset!;
const tileZoom = tileset.getTileZoom(tile.index);
// @ts-ignore
const KEY = tile.index.q ? 'q' : 'i';
// TODO - Tileset2D methods expect tile index in the shape of {x, y, z}
let featureIndex: any = {[KEY]: featureId};
let featureZoom = tileset.getTileZoom(featureIndex);
while (!(featureZoom <= tileZoom)) {
featureIndex = tileset.getParentIndex(featureIndex);
featureZoom = tileset.getTileZoom(featureIndex);
}
return featureIndex[KEY] === tile.index[KEY];
}
}