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;