Pre-built UI controls for common visualization interactions including zoom controls, compass navigation, fullscreen toggle, screenshot capture, and view reset functionality.
All widgets implement a common interface for consistent behavior and integration.
interface Widget {
/** Widget identifier */
id: string;
/** Widget placement on screen */
placement: WidgetPlacement;
/** Get widget DOM element */
getElement(): HTMLElement;
/** Set widget properties */
setProps(props: any): void;
/** Clean up widget resources */
finalize(): void;
}
type WidgetPlacement =
| 'top-left'
| 'top-right'
| 'bottom-left'
| 'bottom-right'
| 'fill';Provides zoom in and zoom out controls for map navigation.
/**
* Zoom control widget with in/out buttons
* Provides standard zoom functionality for map views
*/
class ZoomWidget {
constructor(props?: ZoomWidgetProps);
/** Set widget properties */
setProps(props: Partial<ZoomWidgetProps>): void;
/** Clean up widget */
finalize(): void;
}
interface ZoomWidgetProps {
/** Unique widget identifier */
id?: string;
/** Widget placement position */
placement?: WidgetPlacement;
/** View ID for multi-view setups */
viewId?: string;
/** Custom CSS styles */
style?: React.CSSProperties;
/** Custom CSS class name */
className?: string;
/** Zoom in button label */
zoomInLabel?: string;
/** Zoom out button label */
zoomOutLabel?: string;
/** Transition duration for zoom animations */
transitionDuration?: number;
/** Zoom step size */
zoomStep?: number;
}Usage Example:
import { Deck, ZoomWidget } from "deck.gl";
const deck = new Deck({
container: 'map-container',
initialViewState: {
longitude: -122.4,
latitude: 37.8,
zoom: 10
},
controller: true,
layers: []
});
const zoomWidget = new ZoomWidget({
placement: 'top-left',
zoomInLabel: '+',
zoomOutLabel: '-',
transitionDuration: 200
});
// Add widget to deck
deck.setProps({
widgets: [zoomWidget]
});Navigation compass showing current bearing with click-to-reset functionality.
/**
* Compass navigation widget
* Shows current bearing and provides click-to-reset functionality
*/
class CompassWidget {
constructor(props?: CompassWidgetProps);
/** Set widget properties */
setProps(props: Partial<CompassWidgetProps>): void;
/** Clean up widget */
finalize(): void;
}
interface CompassWidgetProps {
/** Unique widget identifier */
id?: string;
/** Widget placement position */
placement?: WidgetPlacement;
/** View ID for multi-view setups */
viewId?: string;
/** Custom CSS styles */
style?: React.CSSProperties;
/** Custom CSS class name */
className?: string;
/** Transition duration for bearing reset */
transitionDuration?: number;
/** Label for compass (accessibility) */
label?: string;
}Toggle fullscreen mode for the visualization container.
/**
* Fullscreen toggle widget
* Enables entering and exiting fullscreen mode
*/
class FullscreenWidget {
constructor(props?: FullscreenWidgetProps);
/** Set widget properties */
setProps(props: Partial<FullscreenWidgetProps>): void;
/** Clean up widget */
finalize(): void;
}
interface FullscreenWidgetProps {
/** Unique widget identifier */
id?: string;
/** Widget placement position */
placement?: WidgetPlacement;
/** Custom CSS styles */
style?: React.CSSProperties;
/** Custom CSS class name */
className?: string;
/** Enter fullscreen button label */
enterLabel?: string;
/** Exit fullscreen button label */
exitLabel?: string;
/** Fullscreen container element */
container?: HTMLElement;
}Capture screenshots of the current visualization.
/**
* Screenshot capture widget
* Enables downloading visualization as image
*/
class ScreenshotWidget {
constructor(props?: ScreenshotWidgetProps);
/** Set widget properties */
setProps(props: Partial<ScreenshotWidgetProps>): void;
/** Clean up widget */
finalize(): void;
}
interface ScreenshotWidgetProps {
/** Unique widget identifier */
id?: string;
/** Widget placement position */
placement?: WidgetPlacement;
/** Custom CSS styles */
style?: React.CSSProperties;
/** Custom CSS class name */
className?: string;
/** Screenshot button label */
label?: string;
/** Image format for screenshot */
format?: 'png' | 'jpeg';
/** Image quality (0-1, for JPEG) */
quality?: number;
/** Filename for downloaded image */
filename?: string;
}Reset the view to initial state or a predefined view state.
/**
* View reset widget
* Resets view to initial or specified state
*/
class ResetViewWidget {
constructor(props?: ResetViewWidgetProps);
/** Set widget properties */
setProps(props: Partial<ResetViewWidgetProps>): void;
/** Clean up widget */
finalize(): void;
}
interface ResetViewWidgetProps {
/** Unique widget identifier */
id?: string;
/** Widget placement position */
placement?: WidgetPlacement;
/** View ID for multi-view setups */
viewId?: string;
/** Custom CSS styles */
style?: React.CSSProperties;
/** Custom CSS class name */
className?: string;
/** Reset button label */
label?: string;
/** Transition duration for reset animation */
transitionDuration?: number;
/** Target view state (defaults to initial) */
viewState?: ViewState;
}import { Deck, ZoomWidget, CompassWidget, FullscreenWidget } from "deck.gl";
const deck = new Deck({
container: 'map-container',
initialViewState: {
longitude: -122.4,
latitude: 37.8,
zoom: 10
},
controller: true,
layers: myLayers,
// Add widgets
widgets: [
new ZoomWidget({
id: 'zoom',
placement: 'top-left'
}),
new CompassWidget({
id: 'compass',
placement: 'top-right'
}),
new FullscreenWidget({
id: 'fullscreen',
placement: 'bottom-right'
})
]
});Use widgets within React components:
import React from 'react';
import DeckGL, { ZoomWidget, CompassWidget } from '@deck.gl/react';
function MapWithWidgets() {
return (
<div style={{ position: 'relative', width: '100%', height: '600px' }}>
<DeckGL
initialViewState={{
longitude: -122.4,
latitude: 37.8,
zoom: 10
}}
controller={true}
layers={layers}
style={{ width: '100%', height: '100%' }}
/>
{/* React widget components */}
<ZoomWidget placement="top-left" />
<CompassWidget placement="top-right" />
</div>
);
}Customize widget appearance with CSS:
const styledZoomWidget = new ZoomWidget({
placement: 'top-left',
className: 'custom-zoom-widget',
style: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderRadius: '8px',
padding: '8px'
},
zoomInLabel: '⬆',
zoomOutLabel: '⬇'
});Configure widgets for specific views in multi-view setups:
import { Deck, MapView, OrbitView, ZoomWidget, CompassWidget } from "deck.gl";
const deck = new Deck({
views: [
new MapView({ id: 'map', x: '0%', width: '50%' }),
new OrbitView({ id: 'orbit', x: '50%', width: '50%' })
],
widgets: [
// Zoom widget for map view only
new ZoomWidget({
id: 'map-zoom',
placement: 'top-left',
viewId: 'map'
}),
// Compass for both views
new CompassWidget({
id: 'map-compass',
placement: 'top-right',
viewId: 'map'
}),
new CompassWidget({
id: 'orbit-compass',
placement: 'top-right',
viewId: 'orbit'
})
]
});Customize widget appearance with predefined themes:
interface WidgetTheme {
/** Primary color */
primary?: string;
/** Secondary color */
secondary?: string;
/** Background color */
background?: string;
/** Text color */
text?: string;
/** Border radius */
borderRadius?: string;
/** Font family */
fontFamily?: string;
/** Font size */
fontSize?: string;
}
/** Apply theme to all widgets */
function applyWidgetTheme(theme: WidgetTheme): void;
/** Built-in themes */
const WIDGET_THEMES: {
light: WidgetTheme;
dark: WidgetTheme;
minimal: WidgetTheme;
};Usage Example:
import { applyWidgetTheme, WIDGET_THEMES } from "deck.gl";
// Apply dark theme
applyWidgetTheme(WIDGET_THEMES.dark);
// Custom theme
applyWidgetTheme({
primary: '#2196F3',
secondary: '#FFC107',
background: 'rgba(255, 255, 255, 0.9)',
text: '#333333',
borderRadius: '6px'
});Control widgets programmatically:
const zoomWidget = new ZoomWidget({
placement: 'top-left'
});
// Update widget properties
zoomWidget.setProps({
zoomStep: 0.5,
transitionDuration: 500
});
// Listen for widget events (if supported)
zoomWidget.on('zoom', (event) => {
console.log('Zoom level changed:', event.zoom);
});Create custom widgets by implementing the Widget interface:
import { Widget } from "deck.gl";
class CustomInfoWidget implements Widget {
id: string;
placement: WidgetPlacement;
private element: HTMLElement;
constructor(props: CustomInfoWidgetProps) {
this.id = props.id || 'info-widget';
this.placement = props.placement || 'bottom-left';
this.element = this.createElement(props);
}
private createElement(props: CustomInfoWidgetProps): HTMLElement {
const div = document.createElement('div');
div.className = 'custom-info-widget';
div.innerHTML = `
<div class="info-content">
<h3>${props.title}</h3>
<p>${props.content}</p>
</div>
`;
return div;
}
getElement(): HTMLElement {
return this.element;
}
setProps(props: Partial<CustomInfoWidgetProps>): void {
if (props.title || props.content) {
this.element.innerHTML = `
<div class="info-content">
<h3>${props.title}</h3>
<p>${props.content}</p>
</div>
`;
}
}
finalize(): void {
this.element.remove();
}
}
interface CustomInfoWidgetProps {
id?: string;
placement?: WidgetPlacement;
title: string;
content: string;
}Handle widget interactions and state changes:
const zoomWidget = new ZoomWidget({
placement: 'top-left',
onZoomIn: (viewState) => {
console.log('Zooming in, new zoom:', viewState.zoom);
},
onZoomOut: (viewState) => {
console.log('Zooming out, new zoom:', viewState.zoom);
}
});
const compassWidget = new CompassWidget({
placement: 'top-right',
onReset: (viewState) => {
console.log('Bearing reset, new bearing:', viewState.bearing);
}
});