Skip to main content

@deck.gl/widgets

Widgets are UI components around the WebGL2/WebGPU canvas to offer controls and information for a better user experience.

This module contains the following widgets:

Geospatial Widgets

View Widgets

Information Widgets

Control Widgets

Utility Widgets

Installation

Install from NPM

npm install deck.gl
# or
npm install @deck.gl/core @deck.gl/widgets
import {FullscreenWidget} from '@deck.gl/widgets';
import '@deck.gl/widgets/stylesheet.css';

new FullscreenWidget();

Include the Standalone Bundle

<script src="https://unpkg.com/deck.gl@^9.0.0/dist.min.js"></script>
<link href="https://unpkg.com/deck.gl@^9.0.0/dist/stylesheet.css" rel='stylesheet' />
<!-- or -->
<script src="https://unpkg.com/@deck.gl/core@^9.0.0/dist.min.js"></script>
<script src="https://unpkg.com/@deck.gl/widgets@^9.0.0/dist.min.js"></script>
<link href="https://unpkg.com/@deck.gl/widgets@^9.0.0/dist/stylesheet.css" rel='stylesheet' />

Using Widgets

import {Deck} from '@deck.gl/core';
import {
CompassWidget,
ZoomWidget,
FullscreenWidget,
ScreenshotWidget,
} from '@deck.gl/widgets';
import '@deck.gl/widgets/stylesheet.css';

new Deck({
initialViewState: INITIAL_VIEW_STATE,
controller: true,
layers: [
...
],
widgets: [
new ZoomWidget(),
new CompassWidget(),
new FullscreenWidget(),
new ScreenshotWidget()
]
});

The built-in widgets support both dark and light color scheme changes and can be wired up to dynamically respond to color scheme changes like so:

import {Deck} from '@deck.gl/core';
import {
CompassWidget,
ZoomWidget,
FullscreenWidget,
ScreenshotWidget,
DarkGlassTheme,
LightGlassTheme
} from '@deck.gl/widgets';
import '@deck.gl/widgets/stylesheet.css';

/* global window */
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
const widgetTheme = prefersDarkScheme.matches ? DarkGlassTheme : LightGlassTheme;

new Deck({
initialViewState: INITIAL_VIEW_STATE,
controller: true,
layers: [ ... ],
widgets: [
new ZoomWidget({style: widgetTheme}),
new CompassWidget({style: widgetTheme}),
new FullscreenWidget({style: widgetTheme}),
new ScreenshotWidget({style: widgetTheme})
]
});

Using with Multiple Views

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.

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:

new Deck({
views:[
new MapView({id: 'left-map'}),
new MapView({id: 'right-map'})
],
widgets: [
new FullscreenWidget({placement: 'top-right'}),
new ZoomWidget({viewId: 'left-map'}),
new GimbalWidget({viewId: 'right-map'}),
]
})

This configuration will result in the following HTML structure:

<!-- map container -->
<div class="deck-widget-container">
<canvas id="deckgl-overlay">
<!-- size of full map container -->
<div>
<div class="top-right">
</FullscreenWidget>
</div>
</div>
<!-- size and position of the "left-map" view -->
<div>
<div class="top-left">
</ZoomWidget>
</div>
</div>
<!-- size and position of the "right-map" view -->
<div>
<div class="top-left">
</GimbalWidget>
</div>
</div>
</div>

Remarks:

  • Widgets in the default container will be overlapped by view-specific widgets.
  • 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 guide.

Writing new Widgets

A widget should inherit the Widget class. Here is a custom widget that shows a spinner while layers are loading:

import {Deck, Widget} from '@deck.gl/core';

class LoadingIndicator extends Widget {
element?: HTMLDivElement;
size: number;

constructor(options: {
size: number;
}) {
this.size = options.size;
}

onRenderHTML(el: HTMLElement) {
el.className = 'spinner';
el.style.width = `${this.size}px`;
// TODO - create animation for .spinner in the CSS stylesheet
}

onRedraw({layers}) {
const isVisible = layers.some(layer => !layer.isLoaded);
this.rootElement.style.display = isVisible ? 'block' : 'none';
}
}

new Deck({
widgets: [new LoadingIndicator({size: 48})]
});

Themes and Styling

deck.gl widget appearance can be customized using themes and CSS.