Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions docs/api-reference/core/deck.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,20 @@ The following properties are used to initialize a `Deck` instance. Any custom va

#### `canvas` (HTMLCanvasElement | String, optional) {#canvas}

The canvas to render into. Can be either a HTMLCanvasElement or the element id. Will be auto-created if not supplied.
The canvas to render into. It can be either a HTMLCanvasElement or the element id, and will be auto-created if not supplied.

#### `_canvases` ((HTMLCanvasElement | String)[], optional) {#_canvases}

Experimental: presentation canvases for multi-canvas mode. Deck renders into an offscreen default context and presents the result into one `PresentationContext` per canvas entry. String entries are resolved as DOM element ids. Views without an explicit [`canvasId`](./view.md#canvasid) render into the first configured canvas.

Unlike the other initialization settings in this section, `_canvases` is maintained when updated with `setProps()`. Deck diffs the array and creates, reuses, or destroys presentation targets as needed.

Notes:

* Do not supply `canvas` and `_canvases` together.
* `_canvases` is not compatible with `gl`.
* In multi-canvas mode, each canvas gets its own event manager and controller routing.
* `_canvases: []` keeps the offscreen-backed device path active but does not create any presentation targets.

#### `device` ([Device](https://luma.gl/docs/api-reference/core/device)) {#device}

Expand Down Expand Up @@ -616,6 +629,7 @@ Returns:
Notes:

* See the [canvas](#canvas) prop for more information.
* In multi-canvas mode, this returns the first configured presentation canvas.

#### `getViews` {#getviews}

Expand Down Expand Up @@ -658,6 +672,7 @@ Parameters:
+ `y` (number) - top of the bounding box in pixels
+ `width` (number, optional) - width of the bounding box in pixels
+ `height` (number, optional) - height of the bounding box in pixels
+ `canvasId` (string, optional) - limit the search to viewports rendered into the given presentation canvas

Returns:

Expand Down Expand Up @@ -695,13 +710,14 @@ Parameters:
Get the closest pickable and visible object at the given screen coordinate.

```ts
await deck.pickObjectAsync({x, y, radius, layerIds, unproject3D})
await deck.pickObjectAsync({x, y, canvasId, radius, layerIds, unproject3D})
```

Parameters:

* `x` (number) - x position in pixels
* `y` (number) - y position in pixels
* `canvasId` (string, optional) - query within the specified presentation canvas in multi-canvas mode
* `radius` (number, optional) - radius of tolerance in pixels. Default `0`.
* `layerIds` (string[], optional) - a list of layer ids to query from. If not specified, then all pickable and visible layers are queried.
* `unproject3D` (boolean, optional) - if `true`, `info.coordinate` will be a 3D point by unprojecting the `x, y` screen coordinates onto the picked geometry. Default `false`.
Expand All @@ -716,7 +732,7 @@ Returns:
Get all pickable and visible objects within a bounding box.

```ts
await deck.pickObjectsAsync({x, y, width, height, layerIds, maxObjects})
await deck.pickObjectsAsync({x, y, width, height, canvasId, layerIds, maxObjects})
```

Parameters:
Expand All @@ -725,6 +741,7 @@ Parameters:
* `y` (number) - top of the bouding box in pixels
* `width` (number, optional) - width of the bouding box in pixels. Default `1`.
* `height` (number, optional) - height of the bouding box in pixels. Default `1`.
* `canvasId` (string, optional) - query within the specified presentation canvas in multi-canvas mode
* `layerIds` (string[], optional) - a list of layer ids to query from. If not specified, then all pickable and visible layers are queried.
* `maxObjects` (number, optional) - if specified, limits the number of objects that can be returned.

Expand All @@ -744,13 +761,14 @@ Notes:
Get the closest pickable and visible object at the given screen coordinate.

```js
deck.pickObject({x, y, radius, layerIds, unproject3D})
deck.pickObject({x, y, canvasId, radius, layerIds, unproject3D})
```

Parameters:

* `x` (number) - x position in pixels
* `y` (number) - y position in pixels
* `canvasId` (string, optional) - query within the specified presentation canvas in multi-canvas mode
* `radius` (number, optional) - radius of tolerance in pixels. Default `0`.
* `layerIds` (string[], optional) - a list of layer ids to query from. If not specified, then all pickable and visible layers are queried.
* `unproject3D` (boolean, optional) - if `true`, `info.coordinate` will be a 3D point by unprojecting the `x, y` screen coordinates onto the picked geometry. Default `false`.
Expand All @@ -767,13 +785,14 @@ Returns:
Performs deep picking. Finds all close pickable and visible object at the given screen coordinate, even if those objects are occluded by other objects.

```js
deck.pickMultipleObjects({x, y, radius, layerIds, depth, unproject3D})
deck.pickMultipleObjects({x, y, canvasId, radius, layerIds, depth, unproject3D})
```

Parameters:

* `x` (number) - x position in pixels
* `y` (number) - y position in pixels
* `canvasId` (string, optional) - query within the specified presentation canvas in multi-canvas mode
* `radius` (number, optional) - radius of tolerance in pixels. Default `0`.
* `layerIds` (string[], optional) - a list of layer ids to query from. If not specified, then all pickable and visible layers are queried.
* `depth` - Specifies the max number of objects to return. Default `10`. For layers without explicit picking index buffers, only the default depth of 10 unique objects per layer is guaranteed; higher custom depths may return duplicate results for these layers.
Expand All @@ -796,7 +815,7 @@ Notes:
Get all pickable and visible objects within a bounding box.

```js
deck.pickObjects({x, y, width, height, layerIds, maxObjects})
deck.pickObjects({x, y, width, height, canvasId, layerIds, maxObjects})
```

Parameters:
Expand All @@ -805,6 +824,7 @@ Parameters:
* `y` (number) - top of the bouding box in pixels
* `width` (number, optional) - width of the bouding box in pixels. Default `1`.
* `height` (number, optional) - height of the bouding box in pixels. Default `1`.
* `canvasId` (string, optional) - query within the specified presentation canvas in multi-canvas mode
* `layerIds` (string[], optional) - a list of layer ids to query from. If not specified, then all pickable and visible layers are queried.
* `maxObjects` (number, optional) - if specified, limits the number of objects that can be returned.

Expand Down
5 changes: 5 additions & 0 deletions docs/api-reference/core/view.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The `View` class and its subclasses are used to specify where and how your deck.
Views allow you to specify:

* A unique `id`.
* An optional `canvasId` that selects which presentation canvas renders the view in multi-canvas mode.
* The position and extent of the view on the canvas: `x`, `y`, `width`, and `height`.
* Certain camera parameters specifying how your data should be projected into this view, e.g. field of view, near/far planes, perspective vs. orthographic, etc.
* The [controller](./controller.md) to be used for this view. A controller listens to pointer events and touch gestures, and translates user input into changes in the view state. If enabled, the camera becomes interactive.
Expand All @@ -26,6 +27,10 @@ Parameters:

A unique id of the view. In a multi-view use case, this is important for matching view states and place contents into this view.

#### `canvasId` (string, optional) {#canvasid}

When [`Deck._canvases`](./deck.md#_canvases) is supplied, selects which presentation canvas renders this view. If omitted, the view renders into the first configured canvas.

#### `x` (string | number, optional) {#x}

A relative (e.g. `'50%'`) or absolute position. Accepts CSS-like expressions that mix numbers, `%`, `px`, whitespace/parentheses, and `calc()` with `+`/`-` to combine units. Default `0`.
Expand Down
19 changes: 9 additions & 10 deletions docs/api-reference/core/widget.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,13 @@ Additional CSS classnames on the top HTML element.

#### `_container` (string | HTMLDivElement, optional) {#_container}

Experimental. The container that this widget is being attached to. Default to `viewId`.
- If set to `'root'`, the widget is placed relative to the whole deck.gl canvas.
Experimental. Selects the DOM container used for this widget. Defaults to `viewId`.

- If set to `'root'`, the widget is placed relative to the shared widget root.
- If set to a valid view id, the widget is placed relative to that view.
- If set to a HTMLElement, `placement` is ignored and the widget is appended into the given element.
- If set to an HTMLElement, `placement` is ignored and the widget is appended into the given element.

Deck-managed containers remain under one shared widget root. In multi-canvas mode, a view-specific container is positioned using the bounds of the presentation canvas assigned to that view; the widget is not appended to the canvas element.


### Additional `WidgetProps` on UI Widgets
Expand All @@ -53,19 +56,15 @@ Experimental. The container that this widget is being attached to. Default to `v

* Default: `null`

The `viewId` prop controls how a widget interacts with views. If `viewId` is defined, the widget is placed in that view and interacts exclusively with it; otherwise, it is placed in the root widget container and affects all views.
The `viewId` prop controls both positioning and event scope. If defined, the widget is positioned relative to the matching view and only responds to events inside that view. If `null`, the widget is positioned in the shared root widget container and receives events from all views.

When a widget instance is added to Deck, the user can optionally specify a `viewId` that it is attached to (default `null`). If assigned, this widget will only respond to events occurred inside the specific view that matches this id.

The id of the view that the widget is attached to. If `null`, the widget receives events from all views. Otherwise, it only receives events from the view that matches this id.
In multi-canvas mode, the matching view's `canvasId` determines which presentation-canvas bounds are used to position the widget. The widget DOM remains under the shared widget root rather than being reparented into that canvas.

#### `placement` (string, optional) {#placement}

* Default: `'top-left'`

Widget position within the view relative to the map container.

Widget positioning within the view. One of:
Widget positioning within the selected view, or within the shared widget root when `viewId` is `null`. One of:

- `'top-left'`
- `'top-right'`
Expand Down
23 changes: 22 additions & 1 deletion docs/api-reference/widgets/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ new Deck({

Widgets with UI (e.g. a button or panel) can be positioned relative to the deck.gl view they are controlling, via the `viewId` and `placement` props. See [WidgetProps](../core/widget.md#widgetprops).

The `viewId` controls which HTML container will mount to, and the `placement` prop will position it relative to the container it is in, like so:
The `viewId` selects a deck-managed view container under the shared widget root, and the `placement` prop positions the widget within that container:

```ts
new Deck({
Expand Down Expand Up @@ -182,6 +182,27 @@ Remarks:
* Widget UI with dynamic positioning, such as an `InfoWidget`, may not expose the `placement` prop as they control positioning internally.
* For more information about using multiple deck.gl views, see the [Using Multiple Views](../../developer-guide/views.md#using-multiple-views) guide.

### Using with Multiple Canvases

When [`Deck._canvases`](../core/deck.md#_canvases) is supplied, deck.gl still mounts generated widget DOM under one shared `.deck-widget-container`. A widget's `viewId` selects the view used for positioning and event handling; that view's [`canvasId`](../core/view.md#canvasid) determines which presentation-canvas bounds offset the view container. The widget is not reparented into the canvas element.

```ts
new Deck({
parent: document.getElementById('deck-root'),
_canvases: ['canvas-london', 'canvas-tokyo'],
views: [
new MapView({id: 'london', canvasId: 'canvas-london'}),
new MapView({id: 'tokyo', canvasId: 'canvas-tokyo'})
],
widgets: [
new ZoomWidget({viewId: 'london'}),
new ZoomWidget({id: 'tokyo-zoom', viewId: 'tokyo'})
]
});
```

Widgets without a `viewId` stay in the root widget container and are positioned relative to the shared parent, not a specific presentation canvas. Use a common `parent` that covers the presentation canvases when deck-managed widgets need to span them. To opt out of deck-managed positioning, supply an HTMLElement through [`_container`](../core/widget.md#_container).

## Controlled vs Uncontrolled Mode

Many deck.gl widgets support both controlled and uncontrolled modes, similar to React form components.
Expand Down
30 changes: 30 additions & 0 deletions docs/developer-guide/views.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ View classes enable applications to specify one or more rectangular viewports an
A [View](../api-reference/core/view.md) instance defines the following information:

* A unique `id`.
* An optional `canvasId` that selects the presentation canvas in multi-canvas mode.
* The position and extent of the view on the canvas: `x`, `y`, `width`, and `height`.
These properties (and padding) accept CSS-style expressions that combine numbers, percentages, `px` units, parentheses, and `calc()` addition/subtraction so you can mix relative and absolute measurements like `calc(50% - 10px)`.
* Certain camera parameters specifying how your data should be projected into this view, e.g. field of view, near/far planes, perspective vs. orthographic, etc.
Expand Down Expand Up @@ -297,6 +298,14 @@ deck.gl also supports multiple views by taking a `views` prop that is a list of

Views allow the application to specify the position and extent of the viewport (i.e. the target rendering area on the screen) with `x` (left), `y` (top), `width` and `height`. These can be specified in either numbers or CSS-like percentage strings (e.g. `width: '50%'`), which is evaluated at runtime when the canvas resizes.

If [`Deck._canvases`](../api-reference/core/deck.md#_canvases) is supplied, each view may also specify a `canvasId`. In that mode:

* each canvas gets its own presentation target and event manager
* view layout is resolved relative to the assigned canvas, not a global deck rectangle
* controllers and picking are scoped to the assigned canvas

View-specific widgets are positioned relative to the presentation canvas assigned to their `viewId`, while their DOM remains under a shared widget root. See [Using with Multiple Canvases](../api-reference/widgets/overview.md#using-with-multiple-canvases).

Common examples in 3D applications that render a 3D scene multiple times with different "cameras":

* To show views from multiple viewpoints (cameras), e.g. in a split screen setup.
Expand Down Expand Up @@ -379,6 +388,27 @@ function App() {
</TabItem>
</Tabs>

#### Rendering into Multiple Canvases

Multi-canvas mode is useful when a page layout needs several independent map surfaces embedded alongside other content, while still sharing one `Deck` instance.

```js
import {Deck, MapView} from '@deck.gl/core';

const views = [
new MapView({id: 'london', canvasId: 'canvas-london', controller: true}),
new MapView({id: 'tokyo', canvasId: 'canvas-tokyo', controller: true})
];

new Deck({
_canvases: ['canvas-london', 'canvas-tokyo'],
views,
layers
});
```

For a larger standalone TypeScript example, see the multi-canvas cities test app in the [repository](https://github.com/visgl/deck.gl/tree/master/test/apps/multi-canvas-cities).


### Using Multiple Views with View States

Expand Down
25 changes: 17 additions & 8 deletions docs/whats-new.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This page contains highlights of each deck.gl release. Also check our [vis.gl bl

## deck.gl v9.4

Release date: July 2026
Target Release Date: July 2026

deck.gl v9.4 is expected to be the final release in the v9 series. It brings together a collection of completed improvements focused on performance, stability, and usability, and is intended to be a highly compatible, highly recommended upgrade for all v9 applications.

Expand All @@ -26,7 +26,21 @@ deck.gl v9.4 brings additional view and controller improvements on top of the su
- [TerrainExtension](./api-reference/extensions/terrain-extension.md) now supports `GlobeView`, enabling terrain-draped layers on the globe.
- [Tile3DLayer](./api-reference/geo-layers/tile-3d-layer.md) renders correctly on `GlobeView`.

#### Views
### Multi-canvas rendering

deck.gl can now render a single `Deck` instance into multiple HTML canvases.

- [`Deck._canvases`](./api-reference/core/deck.md#_canvases) creates one presentation target per canvas while keeping one shared layer stack and one shared offscreen device context.
- Views can opt into a specific target with [`View.canvasId`](./api-reference/core/view.md#canvasid). Controllers, picking, and layout resolution are all scoped to that canvas.
- Unused canvases are now explicitly cleared when views move or are removed, avoiding stale frames during dynamic layouts.

There is a new standalone TypeScript multi-canvas cities example in the repository that shows four independently navigable city maps with shared scatterplot interactions and view-bound widgets: [test/apps/multi-canvas-cities](https://github.com/visgl/deck.gl/tree/master/test/apps/multi-canvas-cities).

#### View Layout

- A new [`ViewLayout`](./api-reference/widgets/view-layout.md) system makes responsive and dynamic multi-view applications easier to build. Applications define nested, relative view layouts in a simple declarative syntax. The `buildViewsFromViewLayout()` helper then automatically regenerates `View` instances from the specified view layout tree based on browser window size, splitter widget positions, etc.

#### View

- [Views](./api-reference/core/view.md#parameters) now support a `parameters` prop for per-view GPU draw state overrides. `GlobeView` uses this to enable back-face culling by default, and applications can override it with:

Expand All @@ -38,14 +52,10 @@ new GlobeView({
});
```

#### Controllers
#### Controller

- All [controllers](./api-reference/core/controller.md) now support a `doubleClickDragZoom` gesture that enables continuous zooming by double-clicking and dragging vertically.

#### View Layout

- A new [`ViewLayout`](./api-reference/widgets/view-layout.md) system makes responsive and dynamic multi-view applications easier to build. Applications define nested, relative view layouts in a simple declarative syntax. The `buildViewsFromViewLayout()` helper then automatically regenerates `View` instances from the specified view layout tree based on browser window size, splitter widget positions, etc.

### @deck.gl/geo-layers

- [TileLayer](./api-reference/geo-layers/tile-layer.md) now prioritizes tile requests closest to the viewport center, improving perceived load times during panning and zooming.
Expand All @@ -63,7 +73,6 @@ Release date: April 13, 2026

### Widgets


<table style={{border: 0}} align="center">
<tbody>
<tr>
Expand Down
Loading
Loading