-
Notifications
You must be signed in to change notification settings - Fork 2.2k
RFC(geo-layers) SharedTileLayer #10367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| # SharedTile2DLayer (Experimental) | ||
|
|
||
| `_SharedTile2DLayer` is an experimental composite layer for rendering 2D tiled data when multiple layer instances or viewports should reuse one tile-content cache. It is a parallel API to [`TileLayer`](./tile-layer.md), not a replacement for `TileLayer`, `MVTLayer`, or `TerrainLayer`. | ||
|
|
||
| Use `_SharedTile2DLayer` when the same tiled payload should feed multiple views, such as a main map and minimap. The layer keeps selection and visibility state per viewport, while [`_SharedTileset2D`](./shared-tileset-2d.md) owns loading, request scheduling, cache eviction, stats, and TileSource metadata. | ||
|
|
||
| ```ts | ||
| import {Deck, MapView} from '@deck.gl/core'; | ||
| import {BitmapLayer} from '@deck.gl/layers'; | ||
| import { | ||
| _SharedTile2DLayer as SharedTile2DLayer, | ||
| _SharedTileset2D as SharedTileset2D, | ||
| sharedTile2DDeckAdapter | ||
| } from '@deck.gl/geo-layers'; | ||
|
|
||
| const tileset = new SharedTileset2D<ImageBitmap>({ | ||
| adapter: sharedTile2DDeckAdapter, | ||
| minZoom: 0, | ||
| maxZoom: 19, | ||
| getTileData: async ({index, signal}) => { | ||
| const {x, y, z} = index; | ||
| const response = await fetch(`https://tile.openstreetmap.org/${z}/${x}/${y}.png`, {signal}); | ||
| return createImageBitmap(await response.blob()); | ||
| } | ||
| }); | ||
|
|
||
| const layer = new SharedTile2DLayer<ImageBitmap>({ | ||
| id: 'shared-raster-tiles', | ||
| data: tileset, | ||
| renderSubLayers: props => { | ||
| const [[west, south], [east, north]] = props.tile.boundingBox; | ||
| return new BitmapLayer(props, { | ||
| data: null, | ||
| image: props.data, | ||
| bounds: [west, south, east, north] | ||
| }); | ||
| } | ||
| }); | ||
|
|
||
| new Deck({ | ||
| views: [ | ||
| new MapView({id: 'main', controller: true}), | ||
| new MapView({id: 'minimap', x: 16, y: 16, width: 240, height: 160}) | ||
| ], | ||
| initialViewState: {longitude: -122.4, latitude: 37.74, zoom: 11}, | ||
| layers: [layer] | ||
| }); | ||
| ``` | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| npm install deck.gl | ||
| # or | ||
| npm install @deck.gl/core @deck.gl/layers @deck.gl/geo-layers | ||
| ``` | ||
|
|
||
| ```ts | ||
| import {_SharedTile2DLayer as SharedTile2DLayer} from '@deck.gl/geo-layers'; | ||
| import type {SharedTile2DLayerPickingInfo, SharedTile2DLayerProps} from '@deck.gl/geo-layers'; | ||
|
|
||
| new SharedTile2DLayer<TileDataT>(...props: SharedTile2DLayerProps<TileDataT>[]); | ||
| ``` | ||
|
|
||
| ## Properties | ||
|
|
||
| Inherits all properties from base [`Layer`](../core/layer.md). If using the default `renderSubLayers`, supports all [`GeoJSONLayer`](../layers/geojson-layer.md) properties. | ||
|
|
||
| ### `data` (string | string[] | `_SharedTileset2D` | TileSource, optional) {#data} | ||
|
|
||
| - Default: `[]` | ||
|
|
||
| Accepts the same URL-template input as [`TileLayer`](./tile-layer.md#data), a loaders.gl `TileSource`, or an external `_SharedTileset2D`. | ||
|
|
||
| When `data` is a URL template, the layer creates and owns an internal tileset. When `data` is a `TileSource`, the internal tileset uses `TileSource.getTileData()` and adopts supported metadata such as `minZoom`, `maxZoom`, and `boundingBox` unless the layer explicitly overrides those props. When `data` is an external `_SharedTileset2D`, the caller owns and finalizes that tileset. | ||
|
|
||
| ### `getTileData` (Function, optional) {#gettiledata} | ||
|
|
||
| Called for URL-template data with the same tile load props documented by [`TileLayer`](./tile-layer.md#gettiledata). This prop is ignored when `data` is a `TileSource` or external `_SharedTileset2D`. | ||
|
|
||
| ### `renderSubLayers` (Function, optional) {#rendersublayers} | ||
|
|
||
| Receives the loaded tile payload as `props.data` and the shared tile header as `props.tile`. Return one layer, an array of layers, or `null`. | ||
|
|
||
| ### Tile options | ||
|
|
||
| Owned tilesets accept the same core tile options as `TileLayer`: `extent`, `tileSize`, `maxZoom`, `minZoom`, `maxCacheSize`, `maxCacheByteSize`, `zRange`, `maxRequests`, `debounceTime`, `zoomOffset`, `visibleMinZoom`, and `visibleMaxZoom`. | ||
|
|
||
| `refinementStrategy` is intentionally narrower than `TileLayer`: supported values are `'best-available'`, `'no-overlap'`, and `'never'`. Custom refinement callbacks are not supported because tile visibility is view-specific in a shared cache. | ||
|
|
||
| ### Callbacks | ||
|
|
||
| `onViewportLoad`, `onTileLoad`, `onTileUnload`, and `onTileError` follow the `TileLayer` callback shape, using `_SharedTile2DHeader` tile objects. | ||
|
|
||
| ## Picking | ||
|
|
||
| Use `SharedTile2DLayerPickingInfo` for typed picking callbacks. It includes `tile`, `sourceTile`, and `sourceTileSubLayer`, matching `TileLayerPickingInfo`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # SharedTileset2D (Experimental) | ||
|
|
||
| `_SharedTileset2D` is the experimental shared tile-content cache used by [`_SharedTile2DLayer`](./shared-tile-2d-layer.md). It owns tile headers, tile payloads, request scheduling, cache eviction, loaders.gl `TileSource` metadata, live stats, and lifecycle subscriptions. Per-viewport selection and visibility are intentionally owned by the layer's internal views instead of the tileset. | ||
|
|
||
| ```ts | ||
| import { | ||
| _SharedTileset2D as SharedTileset2D, | ||
| sharedTile2DDeckAdapter | ||
| } from '@deck.gl/geo-layers'; | ||
| import type {SharedTileset2DProps} from '@deck.gl/geo-layers'; | ||
|
|
||
| const props: SharedTileset2DProps<ImageBitmap> = { | ||
| adapter: sharedTile2DDeckAdapter, | ||
| getTileData: async ({index, signal}) => { | ||
| const {x, y, z} = index; | ||
| const response = await fetch(`https://tile.openstreetmap.org/${z}/${x}/${y}.png`, {signal}); | ||
| return createImageBitmap(await response.blob()); | ||
| } | ||
| }; | ||
|
|
||
| const tileset = new SharedTileset2D(props); | ||
| ``` | ||
|
|
||
| ## Construction | ||
|
|
||
| ```ts | ||
| import {_SharedTileset2D as SharedTileset2D} from '@deck.gl/geo-layers'; | ||
| import type { | ||
| SharedRefinementStrategy, | ||
| SharedTileset2DAdapter, | ||
| SharedTileset2DBaseProps, | ||
| SharedTileset2DProps, | ||
| SharedTileset2DTileContext, | ||
| SharedTileset2DTraversalContext | ||
| } from '@deck.gl/geo-layers'; | ||
|
|
||
| new SharedTileset2D<TileDataT, ViewStateT>(props: SharedTileset2DProps<TileDataT, ViewStateT>); | ||
| SharedTileset2D.fromTileSource<TileDataT>(tileSource, props); | ||
| ``` | ||
|
|
||
| Provide either `getTileData` or `tileSource`. A shared tileset also needs an adapter before traversal is used. `_SharedTile2DLayer` installs `sharedTile2DDeckAdapter` automatically for deck.gl viewport traversal; applications constructing the tileset directly should usually pass that adapter themselves. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, the adapter is for viewport transversal within the layer. I'd like to see if |
||
|
|
||
| ## TileSource metadata | ||
|
|
||
| When created from a loaders.gl `TileSource`, `_SharedTileset2D` calls `getMetadata()` asynchronously and adopts supported `minZoom`, `maxZoom`, and `boundingBox` metadata. Explicit tileset options win over metadata. Replacing the `tileSource` ignores late metadata from the previous source. | ||
|
|
||
| ## Ownership | ||
|
|
||
| An external `_SharedTileset2D` can be passed to one or more `_SharedTile2DLayer` instances. Those layers do not finalize the external tileset. The owner should call `tileset.finalize()` when the shared cache is no longer needed. | ||
|
|
||
| ## Runtime API | ||
|
|
||
| - `tiles`, `selectedTiles`, `visibleTiles`, `loadingTiles`, and `cacheByteSize` expose current shared cache state. | ||
| - `stats` is a `@probe.gl/stats` `Stats` object with tile cache, visibility, loading, eviction, and consumer counters. | ||
| - `setOptions()` updates effective tileset options. Pass `{replace: true}` as the second argument to replace prior caller options instead of merging them. | ||
| - `reloadAll()` marks selected tiles stale and drops unselected cached tiles. | ||
| - `subscribe()` listens for tile load, tile error, tile unload, metadata/config update, metadata error, and stats change events. | ||
| - `finalize()` aborts in-flight requests and clears the shared cache. | ||
|
|
||
| ## Refinement | ||
|
|
||
| `SharedRefinementStrategy` supports `'best-available'`, `'no-overlap'`, and `'never'`. Unlike `TileLayer`, `_SharedTileset2D` does not accept a custom refinement callback because one tile header may be selected or visible in one viewport and hidden in another. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,13 +2,7 @@ | |
| { | ||
| "type": "category", | ||
| "label": "Overview", | ||
| "items": [ | ||
| "README", | ||
| "whats-new", | ||
| "upgrade-guide", | ||
| "contributing", | ||
| "faq" | ||
| ] | ||
| "items": ["README", "whats-new", "upgrade-guide", "contributing", "faq"] | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like some lint thrashing on unmodified lines. Which is right? |
||
| }, | ||
| { | ||
| "type": "category", | ||
|
|
@@ -120,6 +114,8 @@ | |
| "api-reference/layers/scatterplot-layer", | ||
| "api-reference/mesh-layers/scenegraph-layer", | ||
| "api-reference/aggregation-layers/screen-grid-layer", | ||
| "api-reference/geo-layers/shared-tile-2d-layer", | ||
| "api-reference/geo-layers/shared-tileset-2d", | ||
| "api-reference/mesh-layers/simple-mesh-layer", | ||
| "api-reference/layers/solid-polygon-layer", | ||
| "api-reference/geo-layers/terrain-layer", | ||
|
|
@@ -144,9 +140,7 @@ | |
| { | ||
| "type": "category", | ||
| "label": "Scripting Interface", | ||
| "items": [ | ||
| "api-reference/core/deckgl" | ||
| ] | ||
| "items": ["api-reference/core/deckgl"] | ||
| }, | ||
| { | ||
| "type": "category", | ||
|
|
@@ -203,10 +197,7 @@ | |
| { | ||
| "type": "category", | ||
| "label": "Effects", | ||
| "items": [ | ||
| "api-reference/core/lighting-effect", | ||
| "api-reference/core/post-process-effect" | ||
| ] | ||
| "items": ["api-reference/core/lighting-effect", "api-reference/core/post-process-effect"] | ||
| }, | ||
| { | ||
| "type": "category", | ||
|
|
@@ -289,10 +280,7 @@ | |
| { | ||
| "type": "category", | ||
| "label": "@deck.gl/mapbox", | ||
| "items": [ | ||
| "api-reference/mapbox/overview", | ||
| "api-reference/mapbox/mapbox-overlay" | ||
| ] | ||
| "items": ["api-reference/mapbox/overview", "api-reference/mapbox/mapbox-overlay"] | ||
| }, | ||
| { | ||
| "type": "category", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| This is a standalone experimental SharedTile2DLayer example using one SharedTileset2D to feed | ||
| tiled BitmapLayer sublayers in a main view and minimap on the [deck.gl](http://deck.gl) website. | ||
|
|
||
| ### Usage | ||
|
|
||
| Copy the content of this folder to your project. | ||
|
|
||
| ```bash | ||
| # install dependencies | ||
| npm install | ||
| # or | ||
| yarn | ||
| # bundle and serve the app with vite | ||
| npm start | ||
| ``` | ||
|
|
||
| ### Data Source | ||
|
|
||
| OpenStreetMap raster tiles from [OpenStreetMap contributors](https://www.openstreetmap.org/copyright). | ||
|
|
||
| For more information, check out the | ||
| [documentation of SharedTile2DLayer](../../../docs/api-reference/geo-layers/shared-tile-2d-layer.md). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what the adapter is for if I'm reading these docs for the first time