Search code examples
javascriptopenlayers-3zooming

OpenLayers3: Require Shift for mouse wheel zoom on map


I am trying to disable the zooming using the mouse wheel on an OpenLayers Map. Zooming should only be allowed while the Shift key is hold. According to [1] this can easily be accomplished with

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

map.on('wheel', function (event) {
   if (ol.events.condition.shiftKeyOnly(event) !== true) 
      event.browserEvent.preventDefault();
});

Although it fulfills the desired behavior, I receive many uncaught exceptions on the JavaScript Console. Therefore I don't think that this is a good solution.

Uncaught TypeError: Cannot read property 'preventDefault' of undefined
    at K.<anonymous> (main.js:240)
    at K.b (ol.js:46)
    at K.Sc.b (ol.js:49)
    at K.k.bi (ol.js:129)
    at K.k.yd (ol.js:129)
    at HTMLDivElement.b (ol.js:46)

A check of event.browserEvent and event.browser shows that both are undefined if the wheel event is triggered.

I tried to catch the exception and silently accept it, like in the following. Inexplicably, this shows exception messages on the console but does not show the same behavior anymore - zooming now also works without holding the Shift key.

map.on('wheel', function (event) {
    if (ol.events.condition.shiftKeyOnly(event) !== true) {
        try {
            event.browserEvent.preventDefault();
        } catch(e) {
            console.log("exception.");
        }
    }
});

As I am not sure if it's relevant, but I am also using the libs jQuery and jQueryUI on the website.

[1] https://stackoverflow.com/a/47563819/478545


Solution

  • Try the following code snip , should do the job. Check my code comments for the explanation.

    var map = new ol.Map({
    //disable the default mousewheel interaction
    interactions: ol.interaction.defaults({mouseWheelZoom:false}),
      target: 'map',
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM()
        })
      ],
      view: new ol.View({
        center: [-13553864, 5918250],
        zoom: 4
      })
    });
    //create globaly a mouse wheel interaction and add it to the map 
    var mouseWheelInt = new ol.interaction.MouseWheelZoom();
    map.addInteraction(mouseWheelInt);
    
    
    //now asign a function to the wheel event
    //and finally toggle the activity of your inetraction 
    //depending on the event shift key state
    map.on('wheel', function(evt) {
       mouseWheelInt.setActive(ol.events.condition.shiftKeyOnly(evt));
    });