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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ Each version should:
Ref: http://keepachangelog.com/en/0.3.0/
-->

## deck.gl v9.4

### deck.gl v9.4 Prereleases

- feat(core,react,docs,test): add multi-canvas rendering with view-bound presentation targets
- fix(core): clear and present canvases that no longer have mapped viewports

## deck.gl v9.3

### deck.gl v9.3 Prereleases
Expand Down
47 changes: 42 additions & 5 deletions docs/api-reference/core/deck.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ The following properties are used to initialize a `Deck` instance. Any custom va

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

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

Presentation canvases to use for multi-canvas rendering.

When this prop is defined, 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:

* This prop 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}

luma.gl Device used to manage the application's connection with the GPU. Will be auto-created if not supplied.
Expand Down Expand Up @@ -616,6 +630,23 @@ Returns:
Notes:

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

#### `getEventManager` {#geteventmanager}

Get the event manager for the specified view, or the default canvas if no view id is supplied.

```js
deck.getEventManager(viewId)
```

Parameters:

* `viewId` (string, optional) - the id of the view whose event manager should be returned

Returns:

* An `EventManager` instance, or `null` if deck has not initialized one yet.

#### `getViews` {#getviews}

Expand Down Expand Up @@ -658,6 +689,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 +727,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 +749,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 +758,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 +778,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 +802,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 +832,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 +841,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
10 changes: 10 additions & 0 deletions docs/api-reference/react/deckgl.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ const App = (data) => (

`DeckGL` accepts all [Deck](../core/deck.md#properties) properties, with these additional semantics:

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

Presentation canvases to use when rendering a single `DeckGL` instance into multiple DOM canvases.

This prop mirrors [`Deck.canvases`](../core/deck.md#canvases). When supplied, `DeckGL` creates one DOM host per canvas, binds each [`View`](../core/view.md) to a target canvas through `view.props.canvasId`, and renders view children such as `react-map-gl` maps into the matching canvas host automatically.

Like [`Deck.canvases`](../core/deck.md#canvases), this prop can be updated after mount. `DeckGL` keeps the per-canvas DOM hosts in sync with the current array.

### React Context

#### `ContextProvider` (React.Component, optional) {#contextprovider}
Expand Down Expand Up @@ -149,6 +157,8 @@ The containing view of each element is determined as follows:
- If the element is a direct child of `DeckGL`, it is positioned inside the default (first) view.
- If the element is nested under a `<View id={id}>` tag, it is positioned inside the view corresponding to the `id` prop.

In multi-canvas mode, the element is also rendered inside the DOM host for that view's [`canvasId`](../core/view.md#canvasid).


#### Render callbacks

Expand Down
34 changes: 34 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,12 @@ 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) or [`DeckGL.canvases`](../api-reference/react/deckgl.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, picking, and React view children are scoped to the assigned canvas

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 +386,33 @@ 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.

```tsx
import React from 'react';
import DeckGL from '@deck.gl/react';
import {MapView, View} from '@deck.gl/core';
import {Map} from 'react-map-gl/maplibre';

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

<DeckGL canvases={['canvas-london', 'canvas-tokyo']} views={views} layers={layers}>
<View id="london">
<Map mapStyle="..." />
</View>
<View id="tokyo">
<Map mapStyle="..." />
</View>
</DeckGL>;
```

For a larger 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
4 changes: 4 additions & 0 deletions docs/get-started/using-with-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ The vis.gl community maintains two React libraries that seamlessly work with dec
- `react-map-gl` - a React wrapper for [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/guides) and [MapLibre GL JS](https://maplibre.org/maplibre-gl-js/docs/). Several integration options are discussed in [using with Mapbox](../developer-guide/base-maps/using-with-mapbox.md).
- `@vis.gl/react-google-maps` - a React wrapper for [Google Maps JavaScript API](https://developers.google.com/maps/documentation/javascript). See [using with Google Maps](../developer-guide/base-maps/using-with-google-maps.md).

Starting in v9.4, `DeckGL` can also render into multiple canvases with the `canvases` prop. When a `Map` is nested under a `<View id="...">`, it is mounted into the DOM host for that view automatically, including when that view targets a specific [`canvasId`](../api-reference/core/view.md#canvasid).

See [Views and Projections](../developer-guide/views.md#rendering-into-multiple-canvases) for a full example.

## Using JSX Layers, Views, and Widgets

It is possible to use JSX syntax to create deck.gl layers, views, and widgets as React children of the `DeckGL` React components, instead of providing them as ES6 class instances to the `layers`, `views`, or `widgets` prop, respectively. There are no performance advantages to this syntax but it can allow for a more consistent, React-like coding style.
Expand Down
13 changes: 13 additions & 0 deletions docs/whats-new.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ This page contains highlights of each deck.gl release. Also check our [vis.gl bl

## deck.gl v9.4

Release date: In development

### Multi-canvas rendering

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

- New [`Deck.canvases`](./api-reference/core/deck.md#canvases) and [`DeckGL.canvases`](./api-reference/react/deckgl.md#canvases) props create 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.
- In React, `View` children such as `react-map-gl` maps automatically render into the correct canvas host, so basemaps stay view-bound without a separate canvas API.
- Unused canvases are now explicitly cleared when views move or are removed, avoiding stale frames during dynamic layouts.

There is a new multi-canvas cities example in the repository that shows four independently navigable city maps with shared scatterplot interactions and a toggle between `react-map-gl` basemaps and `BasemapLayer` overlays: [test/apps/multi-canvas-cities](https://github.com/visgl/deck.gl/tree/master/test/apps/multi-canvas-cities).

### Views

- Views 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 `new GlobeView({parameters: {cullMode: 'none'}})`.
Expand Down
Loading
Loading