javascriptreactjsopenlayers

Inverse MouseWheelZoom


There is a project that uses openlayers and react. I came across the need to invert the direction of the mouse wheel when zooming. More precisely, even be able to switch from standard mode to inverted and back.

I tried using the code from this question, but I still get map jumps. (github) Perhaps there is an easier way?

I also tried this option:

let mouseWheelInt = new MouseWheelZoom({
  constrainResolution: true,
  onFocusOnly: true,
  useAnchor: true
});

map.addInteraction(mouseWheelInt);
mouseWheelInt.setActive(false);

window.addEventListener('wheel', (event) => {
  event.stopImmediatePropagation();

  let delta = 0;
  if (wheel_orient === "Inverse") {
    delta = event.deltaY > 0 ? 1 : -1;
  } else {
    delta = event.deltaY < 0 ? 1 : -1;
  }

  let view = map.getView();

  const currentZoom = Math.round(view.getZoom());
  if (currentZoom === undefined) {
    return;
  }

  const newZoom = view.getConstrainedZoom(currentZoom + delta);
  if (newZoom == currentZoom) {
    return;
  }

  if (view.getAnimating()) {
    view.cancelAnimations();
  }

  const coordinates = view.getCenter();

  view.animate({
    zoom: newZoom,
    anchor: coordinates,
    duration: 250,
    easing: easeOut
  });
}, false);


Solution

  • You could patch the interaction code https://github.com/openlayers/openlayers/blob/main/src/ol/interaction/MouseWheelZoom.js#L260 (or create a subclass) to sensibly handle negative value of the maxDelta option

    handleWheelZoom_(map) {
      const view = map.getView();
      if (view.getAnimating()) {
        view.cancelAnimations();
      }
      let delta =
        ((this.maxDelta_ > 0 ? -1 : 1) *
          clamp(
            this.totalDelta_,
            -Math.abs(this.maxDelta_) * this.deltaPerZoom_,
            Math.abs(this.maxDelta_) * this.deltaPerZoom_,
          )) /
        this.deltaPerZoom_;
      if (view.getConstrainResolution() || this.constrainResolution_) {
        // view has a zoom constraint, zoom by 1
        delta = delta ? (delta > 0 ? 1 : -1) : 0;
      }
      zoomByDelta(view, delta, this.lastAnchor_, this.duration_);
    
      this.mode_ = undefined;
      this.totalDelta_ = 0;
      this.lastAnchor_ = null;
      this.startTime_ = undefined;
      this.timeoutId_ = undefined;
    };
    

    Working example https://stackblitz.com/edit/js-behq56?file=package.json,index.html,index.js