deck.gl layers supporting geospatial use cases and GIS formats with WebGL2/WebGPU acceleration
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Core tiling system for visualizing large datasets by loading and rendering only visible tiles with automatic level-of-detail management and efficient caching.
The foundational layer for rendering tiled data with customizable sub-layer rendering and comprehensive tile lifecycle management.
/**
* The TileLayer is a composite layer that makes it possible to visualize very large datasets.
* Instead of fetching the entire dataset, it only loads and renders what's visible in the current viewport.
*/
class TileLayer<DataT = any, ExtraPropsT extends {} = {}> extends CompositeLayer<
ExtraPropsT & Required<_TileLayerProps<DataT>>
> {
constructor(props: TileLayerProps<DataT>);
/** Check if all tiles in the current viewport are loaded */
get isLoaded(): boolean;
/** Custom tile data loading method - override in subclasses */
getTileData(tile: TileLoadProps): Promise<DataT> | DataT | null;
/** Render sub-layers for each tile - override in subclasses */
renderSubLayers(props: RenderSubLayersProps<DataT>): Layer | null | LayersList;
/** Get additional props for tile sub-layers - override in subclasses */
getSubLayerPropsByTile(tile: Tile2DHeader): Partial<LayerProps> | null;
}
interface TileLayerProps<DataT = unknown> extends CompositeLayerProps {
/** URL template or array of templates for tile data */
data: URLTemplate;
/** Optional custom tileset implementation */
TilesetClass?: typeof Tileset2D;
/** Function to render one or more layers for each tile */
renderSubLayers?: (props: RenderSubLayersProps<DataT>) => Layer | null | LayersList;
/** Custom tile data loader function */
getTileData?: ((props: TileLoadProps) => Promise<DataT> | DataT) | null;
/** Called when all tiles in the current viewport are loaded */
onViewportLoad?: ((tiles: Tile2DHeader<DataT>[]) => void) | null;
/** Called when a tile successfully loads */
onTileLoad?: (tile: Tile2DHeader<DataT>) => void;
/** Called when a tile is cleared from cache */
onTileUnload?: (tile: Tile2DHeader<DataT>) => void;
/** Called when a tile failed to load */
onTileError?: (err: any, tile?) => void;
/** The bounding box of the layer's data [minX, minY, maxX, maxY] */
extent?: number[] | null;
/** The pixel dimension of the tiles, usually a power of 2 */
tileSize?: number;
/** The max zoom level of the layer's data */
maxZoom?: number | null;
/** The min zoom level of the layer's data */
minZoom?: number | null;
/** The maximum number of tiles that can be cached */
maxCacheSize?: number | null;
/** The maximum memory used for caching tiles */
maxCacheByteSize?: number | null;
/** How the tile layer refines the visibility of tiles */
refinementStrategy?: RefinementStrategy;
/** Range of minimum and maximum heights in the tile */
zRange?: ZRange | null;
/** The maximum number of concurrent getTileData calls */
maxRequests?: number;
/** Queue tile requests until no new tiles have been requested for at least this many milliseconds */
debounceTime?: number;
/** This offset changes the zoom level at which the tiles are fetched */
zoomOffset?: number;
}
interface RenderSubLayersProps<DataT> extends TileLayerProps<DataT> {
id: string;
data: DataT;
_offset: number;
tile: Tile2DHeader<DataT>;
}
interface TileLayerPickingInfo<DataT = any, SubLayerPickingInfo = PickingInfo>
extends SubLayerPickingInfo {
/** The picked tile */
tile?: Tile2DHeader<DataT>;
/** The tile that emitted the picking event */
sourceTile: Tile2DHeader<DataT>;
/** A layer created by props.renderSubLayer() that emitted the picking event */
sourceTileSubLayer: Layer;
}Usage Examples:
import { TileLayer } from "@deck.gl/geo-layers";
import { GeoJsonLayer } from "@deck.gl/layers";
// Basic tile layer with GeoJSON rendering
const tileLayer = new TileLayer({
id: 'geojson-tiles',
data: 'https://example.com/data/{z}/{x}/{y}.geojson',
renderSubLayers: props => new GeoJsonLayer({
...props,
getFillColor: [160, 160, 180, 200],
getLineColor: [255, 255, 255],
lineWidthMinPixels: 1
}),
pickable: true
});
// Custom tile data loading
const customTileLayer = new TileLayer({
id: 'custom-tiles',
data: 'https://api.example.com/tiles/{z}/{x}/{y}',
getTileData: async ({x, y, z, signal}) => {
const response = await fetch(`https://api.example.com/tiles/${z}/${x}/${y}`, {signal});
return await response.json();
},
renderSubLayers: props => new GeoJsonLayer(props),
onTileLoad: tile => console.log(`Tile loaded: ${tile.id}`),
onTileError: (error, tile) => console.error(`Tile error: ${tile?.id}`, error)
});
// Tile layer with caching configuration
const cachedTileLayer = new TileLayer({
id: 'cached-tiles',
data: 'https://tiles.example.com/{z}/{x}/{y}.pbf',
maxCacheSize: 100,
maxCacheByteSize: 50 * 1024 * 1024, // 50MB
maxRequests: 8,
debounceTime: 100,
renderSubLayers: props => new GeoJsonLayer(props)
});interface TileLoadProps {
/** Tile X coordinate */
x: number;
/** Tile Y coordinate */
y: number;
/** Tile zoom level */
z: number;
/** Bounding box of the tile */
bbox: TileBoundingBox;
/** Generated URL for the tile (if using URL template) */
url?: string | null;
/** AbortSignal for canceling tile requests */
signal?: AbortSignal;
}
interface Tile2DHeader<DataT = any> {
/** Unique identifier for the tile */
id: string;
/** Tile X coordinate */
x: number;
/** Tile Y coordinate */
y: number;
/** Tile zoom level */
z: number;
/** Bounding box of the tile */
bbox: TileBoundingBox;
/** Whether the tile data has finished loading */
isLoaded: boolean;
/** The loaded tile data */
content: DataT | null;
/** Rendered layers for this tile */
layers?: Layer[] | null;
}
type URLTemplate = string | string[];
type RefinementStrategy = 'best-available' | 'no-overlap' | 'never';
type ZRange = [min: number, max: number];
interface TileBoundingBox {
west: number;
south: number;
east: number;
north: number;
}Core tileset management class handling tile loading, caching, and viewport-based tile selection.
/**
* Core tileset management and tile loading logic
* Note: This is an internal API and may change
*/
class _Tileset2D {
constructor(options: Tileset2DProps);
/** Update tileset based on current viewport */
update(viewport: Viewport, options?: {zRange?: ZRange; modelMatrix?: number[]}): number;
/** Get currently selected visible tiles */
selectedTiles: Tile2DHeader[] | null;
/** Check if all selected tiles are loaded */
isLoaded: boolean;
/** Reload all tiles in the tileset */
reloadAll(): void;
/** Clean up tileset resources */
finalize(): void;
}
interface Tileset2DProps {
getTileData: (tile: TileLoadProps) => Promise<any> | any;
onTileLoad: (tile: Tile2DHeader) => void;
onTileError: (error: any, tile: Tile2DHeader) => void;
onTileUnload: (tile: Tile2DHeader) => void;
maxCacheSize?: number | null;
maxCacheByteSize?: number | null;
maxZoom?: number | null;
minZoom?: number | null;
tileSize?: number;
refinementStrategy?: RefinementStrategy;
extent?: number[] | null;
maxRequests?: number;
debounceTime?: number;
zoomOffset?: number;
}/**
* Generate URL from template and tile coordinates
* Note: This is an internal API and may change
*/
function _getURLFromTemplate(template: URLTemplate, tile: TileLoadProps): string;
/**
* Calculate visible tile indices for given viewport
*/
function getTileIndices(
viewport: Viewport,
maxZoom?: number,
minZoom?: number,
tileSize?: number
): {x: number, y: number, z: number}[];
/**
* Convert tile coordinates to bounding box
*/
function tileToBoundingBox(
viewport: Viewport,
x: number,
y: number,
z: number
): TileBoundingBox;
/**
* Check if bounds represent a geographic bounding box
*/
function isGeoBoundingBox(bounds: any): bounds is GeoBoundingBox;
/**
* Check if data represents a URL template
*/
function isURLTemplate(data: any): data is URLTemplate;Install with Tessl CLI
npx tessl i tessl/npm-deck-gl--geo-layers