UNPKG

@deck.gl-community/layers

Version:

Addon layers for deck.gl

156 lines (136 loc) 3.9 kB
// deck.gl-community // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors import {CompositeLayer, Layer} from '@deck.gl/core'; import {TileLayer, TileLayerProps} from '@deck.gl/geo-layers'; import {BitmapLayer, GeoJsonLayer, PathLayer} from '@deck.gl/layers'; import type {TileSource} from '@loaders.gl/loader-utils'; /* global window */ const devicePixelRatio = (typeof window !== 'undefined' && window.devicePixelRatio) || 1; export type TileSourceLayerProps = TileLayerProps & { tileSource: TileSource<any>; showTileBorders?: boolean; }; /** * A Deck.gl layer that renders a tile source * Autodiscovers type of content (vector tile, bitmap, ...) * Can render debug borders around tiles * TODO - Change debug border color based on zoom level */ export class TileSourceLayer extends CompositeLayer<TileSourceLayerProps> { static layerName = 'TileSourceLayer'; static defaultProps = { ...TileLayer.defaultProps, showTileBorders: true }; state: { tileSource: TileSource<any> | null; } = undefined!; initializeState() { this.setState({ tileSource: null }); } updateState({props, changeFlags}) { this.setState({ tileSource: props.tileSource }); } renderLayers() { const {tileSource, showTileBorders, metadata, onTilesLoad} = this.props as any; const minZoom = metadata?.minZoom || 0; const maxZoom = metadata?.maxZoom || 30; return [ new TileLayer({ // HACK: Trigger new layer via id prop to force clear tile cache id: String(tileSource.url), getTileData: tileSource.getTileData, // Assume the pmtiles file support HTTP/2, so we aren't limited by the browser to a certain number per domain. maxRequests: 20, pickable: true, onViewportLoad: onTilesLoad, autoHighlight: showTileBorders, highlightColor: [60, 60, 60, 40], minZoom, maxZoom, tileSize: 256, // TOOD - why is this needed? zoomOffset: devicePixelRatio === 1 ? -1 : 0, renderSubLayers: renderSubLayers as any, // Custom prop tileSource, showTileBorders }) ]; } } function renderSubLayers( props: TileSourceLayerProps & {tile: {index; bbox: {west; south; east; north}}} ) { const { tileSource, showTileBorders, minZoom, maxZoom, tile: { index: {z: zoom}, bbox: {west, south, east, north} } } = props as any; const layers: Layer[] = []; const borderColor = zoom <= minZoom || zoom >= maxZoom ? [255, 0, 0, 255] : [0, 0, 255, 255]; switch (tileSource.mimeType) { case 'application/vnd.mapbox-vector-tile': layers.push( new GeoJsonLayer({ id: `${props.id}-geojson`, data: props.data as any, pickable: true, getFillColor: [0, 190, 80, 255], lineWidthScale: 500, lineWidthMinPixels: 0.5 }) ); break; case 'image/png': case 'image/jpeg': case 'image/webp': case 'image/avif': layers.push( new BitmapLayer( props as any, { data: null, image: props.data, bounds: [west, south, east, north], pickable: true } as any ) ); break; default: // eslint-disable-next-line no-console console.error('Unknown tile mimeType', tileSource?.mimeType); } // Debug tile borders if (showTileBorders) { layers.push( new PathLayer({ id: `${props.id}-border`, data: [ [ [west, north], [west, south], [east, south], [east, north], [west, north] ] ], getPath: (d) => d, getColor: borderColor as any, widthMinPixels: 4 }) ); } return layers; }