Skip to content
Merged
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
6 changes: 5 additions & 1 deletion docs/api-reference/core/controller.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ The base Controller class supports the following options:
* `dragPan` (boolean) - enable panning with pointer drag. Default `true`
* `dragRotate` (boolean) - enable rotating with pointer drag. Default `true`
* `doubleClickZoom` (boolean) - enable zooming with double click. Default `true`
* `touchZoom` (boolean) - enable zooming with multi-touch. Default `true`
* `doubleClickDragZoom` (boolean) - enable zooming by double clicking/tapping and dragging. Default `true`
* `touchZoom` (boolean) - enable zooming with multi-touch pinch. Default `true`
* `touchRotate` (boolean) - enable rotating with multi-touch. Use two-finger rotating gesture for horizontal and three-finger swiping gesture for vertical rotation. Default `false`
* `keyboard` (boolean | object) - enable interaction with keyboard. Default `true`. If an object is supplied, it may contain the following fields to customize the keyboard behavior:
* `zoomSpeed` (number) - speed of zoom using +/- keys. Default `2`.
Expand All @@ -26,6 +27,8 @@ The base Controller class supports the following options:
* `inertia` (boolean | number) - Enable inertia after panning/pinching. If a number is provided, indicates the duration of time over which the velocity reduces to zero, in milliseconds. Default `false`.
* `maxBounds` (`[min: number[], max: number[]]`) - constrain camera to the specified bounding box. Different type of views may handle this constraint differently.

> **Mobile users:** See [Optimization for Mobile](../../developer-guide/tips-and-tricks.md#optimization-for-mobile) for CSS and browser event guards that help prevent native selection, tap highlight, and touch callout UI during repeated touch gestures.

## Methods

> A controller is not meant to be instantiated by the application. The following methods are documented for creating custom controllers that extend the base Controller class.
Expand Down Expand Up @@ -116,6 +119,7 @@ Note that the following events are always toggled on/off by user options:
* `touchZoom` - `['pinch']`
* `touchRotate` - `['pinch', 'multipan']`
* `doubleClickZoom` - `['dblclick']`
* `doubleClickDragZoom` - `['pointerdown', 'pointermove', 'pointerup', 'pointercancel']`
* `keyboard` - `['keydown']`


Expand Down
30 changes: 30 additions & 0 deletions docs/developer-guide/tips-and-tricks.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,36 @@ If this is an issue, set the `isolation` CSS prop on the `DeckGL` parent element

## Optimization for Mobile

### Mobile Browser Touch UI

For mobile experiences using a deck.gl [Controller](../api-reference/core/controller.md), use CSS guards on the Deck canvas/root element so repeated touch gestures do not trigger browser selection, tap highlight, or WebKit touch callouts:

```css
#deck-root,
#deck-root canvas {
touch-action: none;
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: transparent;
}
```

Some iOS embeds may still surface native callout UI during long-press or rapid double-tap gestures. In those cases, prevent the browser-native UI events that originate from the canvas without stopping pointer event propagation. The controller still needs deck.gl's pointer events to receive the gesture sequence.

```js
const root = document.getElementById('deck-root');
const preventCanvasBrowserUI = event => {
if (event.target instanceof HTMLCanvasElement) {
event.preventDefault();
}
};

for (const type of ['contextmenu', 'selectstart', 'gesturestart', 'gesturechange', 'gestureend']) {
root.addEventListener(type, preventCanvasBrowserUI, {passive: false});
}
```

### Experimental Memory Usage Controls

The `Deck` class supports the following experimental props to aggressively reduce memory usage on memory-restricted devices:
Expand Down
23 changes: 23 additions & 0 deletions examples/website/globe/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ function getDate(data: DailyFlights[], t: number) {
}

export async function renderToDOM(container: HTMLDivElement) {
// See https://deck.gl/docs/developer-guide/tips-and-tricks#optimization-for-mobile
// for browser UI guards that keep mobile controller gestures focused on the canvas.
addCanvasInteractionGuards(container);

const root = createRoot(container);
root.render(<App />);

Expand Down Expand Up @@ -186,3 +190,22 @@ export async function renderToDOM(container: HTMLDivElement) {
root.render(<App data={data} />);
}
}

function addCanvasInteractionGuards(container: HTMLDivElement): void {
const preventCanvasBrowserUI = (event: Event) => {
if (event.target instanceof HTMLCanvasElement) {
event.preventDefault();
}
};
const listenerOptions = {passive: false};

for (const type of [
'contextmenu',
'selectstart',
'gesturestart',
'gesturechange',
'gestureend'
]) {
container.addEventListener(type, preventCanvasBrowserUI, listenerOptions);
}
}
53 changes: 38 additions & 15 deletions examples/website/globe/index.html
Original file line number Diff line number Diff line change
@@ -1,18 +1,41 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>deck.gl Example</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {margin: 0; font-family: sans-serif; width: 100vw; height: 100vh; overflow: hidden; background: #111;}
</style>
</head>
<body>
<div id="app"></div>
</body>
<script type="module">
import {renderToDOM} from './app.tsx';
renderToDOM(document.getElementById('app'));
</script>
<head>
<meta charset="utf-8" />
<title>deck.gl Example</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
html,
body,
#app {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
overscroll-behavior: none;
font-family: sans-serif;
background: #111;
}

/*
* See https://deck.gl/docs/developer-guide/tips-and-tricks#optimization-for-mobile
* for CSS guards when using deck.gl controllers in mobile experiences.
*/
#app,
#app canvas {
touch-action: none;
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: transparent;
}
</style>
</head>
<body>
<div id="app"></div>
</body>
<script type="module">
import {renderToDOM} from './app.tsx';
renderToDOM(document.getElementById('app'));
</script>
</html>
Loading
Loading