or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

3d-tiles.mdanimation.mdindex.mdspatial-indexing.mdterrain.mdtile-layers.mdvector-tiles.md
tile.json

tile-layers.mddocs/

Tile-based Data Visualization

Core tiling system for visualizing large datasets by loading and rendering only visible tiles with automatic level-of-detail management and efficient caching.

Capabilities

TileLayer

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)
});

Core Types

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;
}

Tileset Management

Tileset2D (Internal)

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;
}

URL Template Utilities

/**
 * 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;