Openlayers - Custom Context Menu

by Jonatas Walker

HTML

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/ol.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ol.js"></script>
<script src="https://cdn.jsdelivr.net/npm/ol-contextmenu"></script>
<div id="map" tabindex="0"></div>

CSS

@import url(https://fonts.googleapis.com/css?family=Open+Sans);
html, body, #map{
  width:100%;
  height:100%;
  margin: 0;
  overflow:hidden;
}
body {
  font: 1em/1.5 "Open Sans",Helvetica,Arial,sans-serif;
  color: #222;
  font-weight: 400;
}
#map {
  position:absolute;
  z-index:1;
  top:0; bottom:0;
}
.ol-control button { 
  background-color: rgba(40, 40, 40, 0.8) !important;
}
.ol-control button:hover { 
  background-color: rgba(40, 40, 40, 1) !important;
}

JavaScript

var view = new ol.View({ center: [0, 0], zoom: 2 }),
    vectorLayer = new ol.layer.Vector({ source: new ol.source.Vector() }),
    baseLayer = new ol.layer.Tile({ source: new ol.source.OSM() }),
    map = new ol.Map({
      target: 'map',
      view: view,
      layers: [baseLayer, vectorLayer]
    });

var pinIcon = 'https://cdn.jsdelivr.net/gh/jonataswalker/ol-contextmenu@604befc46d737d814505b5d90fc171932f747043/examples/img/pin_drop.png';
var centerIcon = 'https://cdn.jsdelivr.net/gh/jonataswalker/ol-contextmenu@604befc46d737d814505b5d90fc171932f747043/examples/img/center.png';
var listIcon = 'https://cdn.jsdelivr.net/gh/jonataswalker/ol-contextmenu@604befc46d737d814505b5d90fc171932f747043/examples/img/view_list.png';

var contextmenuItems = [
  {
    text: 'Center map here',
    classname: 'bold',
    icon: centerIcon,
    callback: center
  },
  {
    text: 'Some Actions',
    icon: listIcon,
    items: [
      {
        text: 'Center map here',
        icon: centerIcon,
        callback: center
      },
      {
        text: 'Add a Marker',
        icon: pinIcon,
        callback: marker
      }
    ]
  },
  {
    text: 'Add a Marker',
    icon: pinIcon,
    callback: marker
  },
  '-' // this is a separator
];

var contextmenu = new ContextMenu({
  width: 180,
  items: contextmenuItems
});
map.addControl(contextmenu);

var removeMarkerItem = {
  text: 'Remove this Marker',
  classname: 'marker',
  callback: removeMarker
};

contextmenu.on('open', function (evt) {
  var feature =	map.forEachFeatureAtPixel(evt.pixel, ft => ft);
  
  if (feature && feature.get('type') === 'removable') {
    contextmenu.clear();
    removeMarkerItem.data = { marker: feature };
    contextmenu.push(removeMarkerItem);
  } else {
    contextmenu.clear();
    contextmenu.extend(contextmenuItems);
    contextmenu.extend(contextmenu.getDefaultItems());
  }
});

map.on('pointermove', function (e) {
  if...