ContextMenuWidget (Experimental)
Displays a context menu on right-click events with customizable menu items based on picked objects.
- JavaScript
- TypeScript
- React
import {Deck} from '@deck.gl/core';
import {ScatterplotLayer} from '@deck.gl/layers';
import {_ContextMenuWidget as ContextMenuWidget} from '@deck.gl/widgets';
import '@deck.gl/widgets/stylesheet.css';
let points = [[-122.4, 37.78]];
const renderLayer = () =>
new ScatterplotLayer({
id: 'points',
data: points,
getPosition: d => d,
getRadius: 5000,
getFillColor: [200, 0, 80],
pickable: true
});
const deck = new Deck({
initialViewState: {
longitude: -122.4,
latitude: 37.78,
zoom: 10
},
controller: true,
layers: [renderLayer()],
widgets: [
new ContextMenuWidget({
getMenuItems: info => {
if (info.layer?.id === 'points') {
return [{value: 'delete', label: 'Delete point'}];
} else {
return [{value: 'add', label: 'Add point'}];
}
},
onMenuItemSelected: (key, info) => {
if (key === 'add' && info.coordinate) {
points = points.concat([info.coordinate]);
}
if (key === 'delete' && info.index >= 0) {
points = points.filter((_, index) => index !== info.index);
}
deck.setProps({layers: [renderLayer()]});
}
})
]
});
import {Deck, type PickingInfo} from '@deck.gl/core';
import {ScatterplotLayer} from '@deck.gl/layers';
import {_ContextMenuWidget as ContextMenuWidget} from '@deck.gl/widgets';
import '@deck.gl/widgets/stylesheet.css';
type Point = [longitude: number, latitude: number];
let points: Point[] = [[-122.4, 37.78]];
const renderLayer = () =>
new ScatterplotLayer<Point>({
id: 'points',
data: points,
getPosition: d => d,
getRadius: 5000,
getFillColor: [200, 0, 80],
pickable: true
});
const deck = new Deck({
initialViewState: {
longitude: -122.4,
latitude: 37.78,
zoom: 10
},
controller: true,
layers: [renderLayer()],
widgets: [
new ContextMenuWidget({
getMenuItems: (info: PickingInfo<Point>) => {
if (info.layer?.id === 'points') {
return [{value: 'delete', label: 'Delete point'}];
} else {
return [{value: 'add', label: 'Add point'}];
}
},
onMenuItemSelected: (key: string, info: PickingInfo<Point>) => {
if (key === 'add' && info.coordinate) {
points = points.concat([info.coordinate as Point]);
}
if (key === 'delete' && info.index >= 0) {
points = points.filter((_, index) => index !== info.index);
}
deck.setProps({layers: [renderLayer()]});
}
})
]
});
import React, {useState, useCallback} from 'react';
import DeckGL, {_ContextMenuWidget as ContextMenuWidget} from '@deck.gl/react';
import {ScatterplotLayer} from '@deck.gl/layers';
import type {PickingInfo} from '@deck.gl/core';
import '@deck.gl/widgets/stylesheet.css';
type Point = [longitude: number, latitude: number];
function App() {
const [points, setPoints] = useState<Point[]>([[-122.4, 37.78]]);
const getMenuItems = useCallback((info: PickingInfo<Point>) => {
if (info.layer?.id === 'points') {
return [{value: 'delete', label: 'Delete point'}];
} else {
return [{value: 'add', label: 'Add point'}];
}
}, []);
const onMenuItemSelected = useCallback((key: string, info: PickingInfo<Point>) => {
if (key === 'add' && info.coordinate) {
setPoints(current => current.concat([info.coordinate as Point]));
}
if (key === 'delete' && info.index >= 0) {
setPoints(current => current.filter((_, index) => index !== info.index));
}
}, []);
return (
<DeckGL
initialViewState={{
longitude: -122.4,
latitude: 37.78,
zoom: 10
}}
controller
layers={[
new ScatterplotLayer<Point>({
id: 'points',
data: points,
getPosition: d => d,
getRadius: 5000,
getFillColor: [200, 0, 80],
pickable: true
})
]}
>
<ContextMenuWidget
getMenuItems={getMenuItems}
onMenuItemSelected={onMenuItemSelected}
/>
</DeckGL>
);
}
Installation
npm install deck.gl
# or
npm install @deck.gl/core @deck.gl/layers @deck.gl/widgets @deck.gl/react
import {_ContextMenuWidget as ContextMenuWidget, type ContextMenuWidgetProps} from '@deck.gl/widgets';
import '@deck.gl/widgets/stylesheet.css';
new ContextMenuWidget({} satisfies ContextMenuWidgetProps);
To use pre-bundled scripts:
<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' />
new deck._ContextMenuWidget({});
Types
ContextMenuWidgetProps
The ContextMenuWidget accepts the generic WidgetProps and:
getMenuItems (Function)
Function that returns menu items based on the picked object. Receives the following parameters:
pickInfo(PickingInfo) - descriptor of what's under the pointer
Expected to return an array of ContextWidgetMenuItem objects, or null if no menu should be displayed.
onMenuItemSelected (Function, optional)
Callback invoked when a menu item is selected. Receives the following parameters:
value(string) - the value of the selected menu itempickInfo(PickingInfo) - descriptor of what's under the pointer
placement (string, optional)
Position content relative to the anchor.
One of bottom | left | right | top | bottom-start | bottom-end | left-start | left-end | right-start | right-end | top-start | top-end
- Default:
'right'
offset (number)
Pixel offset from the anchor
- Default:
10
arrow (false | number | [number, number])
Show an arrow pointing at the anchor. Value can be one of the following:
-
false- do not display an arrow -
number- pixel size of the arrow -
[width: number, height: number]- pixel size of the arrow -
Default:
10
ContextWidgetMenuItem
Menu item definition:
label(string) - Display text for the menu itemvalue(string, optional) - Unique identifier for the menu item. If not supplied, then the item is not interactive.icon(string, optional) - Data url of an icon that should be displayed with the menu item