A contextmenu
extension for OpenLayers. Requires OpenLayers v7.0.0 or higher.

Demo
JSFiddle
CodeSandbox
How to use it?
NPM
npm install ol-contextmenu
Load CSS and Javascript:
<link href="https://cdn.jsdelivr.net/npm/ol-contextmenu@latest/dist/ol-contextmenu.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/ol-contextmenu"></script>
CDN Hosted - UNPKG
Load CSS and Javascript:
<link href="https://unpkg.com/ol-contextmenu/dist/ol-contextmenu.css" rel="stylesheet">
<script src="https://unpkg.com/ol-contextmenu"></script>
Self hosted
Download latest release and (obviously) load CSS and Javascript.
Instantiate with some options and add the Control
const contextmenu = new ContextMenu({
width: 170,
defaultItems: true,
items: [
{
text: 'Center map here',
classname: 'some-style-class',
callback: center,
},
{
text: 'Add a Marker',
classname: 'some-style-class',
icon: 'img/marker.png',
callback: marker,
},
'-',
],
});
map.addControl(contextmenu);
If you provide items {Array}
a submenu will be created as a child of the current item.
const all_items = [
{
text: 'Some Actions',
items: [
{
text: 'Action 1',
callback: action,
},
{
text: 'Other action',
callback: action2,
},
],
},
{
text: 'Add a Marker',
icon: 'img/marker.png',
callback: marker,
},
'-',
];
Would you like to propagate custom data to the callback handler?
const removeMarker = function (obj) {
vectorLayer.getSource().removeFeature(obj.data.marker);
};
const removeMarkerItem = {
text: 'Remove this Marker',
icon: 'img/marker.png',
callback: removeMarker,
};
let restore = false;
contextmenu.on('open', function (evt) {
const feature = map.forEachFeatureAtPixel(evt.pixel, function (ft, l) {
return ft;
});
if (feature) {
contextmenu.clear();
removeMarkerItem.data = { marker: feature };
contextmenu.push(removeMarkerItem);
restore = true;
} else if (restore) {
contextmenu.clear();
contextmenu.extend(contextmenu_items);
contextmenu.extend(contextmenu.getDefaultItems());
restore = false;
}
});
API
Constructor
options
is an object with the following possible properties:
eventType
: contextmenu
; The listening event type (You could use 'click'
, 'dblclick'
)defaultItems
: true
; Whether the default items (which are: Zoom In/Out) are enabledwidth
: 150
; The menu's widthitems
: []
; An array of object|string
Methods
Remove all elements from the menu.
Close the menu programmatically.
@param {Array} arr
Add items to the menu. This pushes each item in the provided array to the end of the menu.
Example:
const contextmenu = new ContextMenu();
map.addControl(contextmenu);
const add_later = [
'-',
{
text: 'Add a Marker',
icon: 'img/marker.png',
callback: marker,
},
];
contextmenu.extend(add_later);
@param {Object|String} item
Insert the provided item at the end of the menu.
Remove the first item of the menu.
Remove the last item of the menu.
Get an array of default items.
Whether the menu is open.
@param {Array} pixel
Update menu's position.
Events
If you want to disable this plugin under certain circumstances, listen to beforeopen
contextmenu.on('beforeopen', function (evt) {
const feature = map.forEachFeatureAtPixel(evt.pixel, function (ft, l) {
return ft;
});
if (feature) {
contextmenu.enable();
} else {
contextmenu.disable();
}
});
Listen and make some changes when context menu opens
contextmenu.on('open', function (evt) {
const feature = map.forEachFeatureAtPixel(evt.pixel, function (ft, l) {
return ft;
});
if (feature) {
}
});
contextmenu.on('close', function (evt) {
});