mapbox-gl-js icon indicating copy to clipboard operation
mapbox-gl-js copied to clipboard

Easier way to disable all rotation and pitch

Open stevage opened this issue 6 years ago • 8 comments

Sadly, most of the maps that I work on have no need for any 3D features or orientations other than north-up. But by default all these navigation features are enabled, which means eventually some poor user accidentally holds down control and gets very confused. Then I fumble through finding how to disable them all:

var map = new mapboxgl.Map({
...
        pitchWithRotate: false,
        dragRotate: false,
        touchZoomRotate: false
).addControl(new mapboxgl.NavigationControl({ showCompass: false }), 'top-left');

Just a suggestion to consider making this easier, like maybe an option such as "fixedViewport: true" that would imply the others. Or just a note in the documentation explaining the above.

stevage avatar Apr 18 '18 00:04 stevage

Want to submit a PR with an example containing the above code?

jfirebaugh avatar Apr 18 '18 00:04 jfirebaugh

Interesting. There is this example "Disable map rotation" which purports to just disable rotation, but actually also disables pitch, which I wouldn't have expected.

Although, in that light, now that I read If false , the map's pitch (tilt) control with "drag to rotate" interaction will be disabled." that makes sense - it just wasn't obvious to me at first.

stevage avatar Apr 19 '18 01:04 stevage

The Disable map rotation example also fails to disable Shift+Left/Right Arrow rotations.

andrewharvey avatar Jul 31 '18 08:07 andrewharvey

Anyone know how I can disable also the SHIFT + arrow keys?

danichim avatar Sep 14 '18 07:09 danichim

@danichim my solution is fork the keyboardhandler, and change the keyboard handle, remove code to change rotation and pitch https://github.com/mapbox/mapbox-gl-js/blob/master/src/ui/handler/keyboard.js

then

m.keyboard.disable();
m.keyboard = new KeyboardWithoutPitchAndRotateHandler(m);
m.keyboard.enable();
import { Map } from "mapbox-gl";

const panStep = 100,
  bearingStep = 15,
  pitchStep = 10;

export class KeyboardWithoutPitchAndRotateHandler {
  _map: Map;
  _el: HTMLElement;
  _enabled: boolean = false;

  constructor(map: Map) {
    this._map = map;
    this._el = map.getCanvasContainer();
  }

  isEnabled() {
    return !!this._enabled;
  }

  enable() {
    if (this.isEnabled()) return;
    this._el.addEventListener("keydown", this._onKeyDown, false);
    this._enabled = true;
  }

  disable() {
    if (!this.isEnabled()) return;
    this._el.removeEventListener("keydown", this._onKeyDown);
    this._enabled = false;
  }

  _onKeyDown = (e: KeyboardEvent) => {
    if (e.altKey || e.ctrlKey || e.metaKey) return;

    let zoomDir = 0;
    let bearingDir = 0;
    let pitchDir = 0;
    let xDir = 0;
    let yDir = 0;

    switch (e.keyCode) {
      case 61:
      case 107:
      case 171:
      case 187:
        zoomDir = 1;
        break;

      case 189:
      case 109:
      case 173:
        zoomDir = -1;
        break;

      case 37:
        if (e.shiftKey) {
          // bearingDir = -1;
        } else {
          e.preventDefault();
          xDir = -1;
        }
        break;

      case 39:
        if (e.shiftKey) {
          // bearingDir = 1;
        } else {
          e.preventDefault();
          xDir = 1;
        }
        break;

      case 38:
        if (e.shiftKey) {
          // pitchDir = 1;
        } else {
          e.preventDefault();
          yDir = -1;
        }
        break;

      case 40:
        if (e.shiftKey) {
          // pitchDir = -1;
        } else {
          yDir = 1;
          e.preventDefault();
        }
        break;

      default:
        return;
    }

    const map = this._map;
    const zoom = map.getZoom();

    map.easeTo(
      {
        duration: 300,
        delayEndEvents: 500,
        easing: easeOut,

        zoom: zoomDir
          ? Math.round(zoom) + zoomDir * (e.shiftKey ? 2 : 1)
          : zoom,
        bearing: map.getBearing() + bearingDir * bearingStep,
        pitch: map.getPitch() + pitchDir * pitchStep,
        offset: [-xDir * panStep, -yDir * panStep],
        center: map.getCenter(),
      },
      { originalEvent: e },
    );
  };
}

function easeOut(t: number) {
  return t * (2 - t);
}

morlay avatar Jan 17 '19 02:01 morlay

There are easy ways to disable tilt for Android and iOS. Is there an equivalent for web?

mb72 avatar Feb 03 '22 05:02 mb72

+1 Pitch can be disabled easily using setMaxPitch or whatever, but to properly disable rotation you have to dig through the code and do all kinds of hacks. The "disable rotation" example doesn't actually disable rotation, just part of the interaction handlers. The keyboard and the navigationbutton (if you add it) can still rotate..

fr-an-k avatar Apr 08 '22 02:04 fr-an-k

I believe the keyboard rotation/pitch is solved by map.keyboard.disableRotation(). I have suggested this as an addition to this page.

oliverbenns avatar Dec 29 '22 19:12 oliverbenns