Mapbox-gl-js: Support dragPan.disable() mid-drag

Created on 11 Apr 2016  路  13Comments  路  Source: mapbox/mapbox-gl-js

mapbox-gl-js version: Master branch

Steps to Trigger Behavior

  1. Start dragging the map (mouse or touch input)
  2. Set map.dragPan.disable() during the drag event

    Expected Behavior

Dragging should no longer move the map.

Actual Behavior

Map will continue being draggable until mouseup or touchend

Afaik, the root issue is that event listeners can't be removed until the ongoing mousedown / touchstart event is finished.

Workaround:

Update the following drag_pan.js handlers:


_onDown: function (e) {
        if (this._ignoreEvent(e)) return;
        if (this.isActive()) return;
        if (!this._enabled) { // Added check for _enabled
            this._inertia = [];
            return;
        };

        if (e.touches) {
            document.addEventListener('touchmove', this._onMove);
            document.addEventListener('touchend', this._onTouchEnd);
        } else {
            document.addEventListener('mousemove', this._onMove);
            document.addEventListener('mouseup', this._onMouseUp);
        }

        this._active = false;
        this._startPos = this._pos = DOM.mousePos(this._el, e);
        this._inertia = [[Date.now(), this._pos]];
    },

    _onMove: function (e) {
        if (this._ignoreEvent(e)) return;
         if (!this._enabled) { // Added check for _enabled
            this._inertia = [];
            return;
        };

        if (!this.isActive()) {
            this._active = true;
            this._fireEvent('dragstart', e);
            this._fireEvent('movestart', e);
        }

        var pos = DOM.mousePos(this._el, e),
            map = this._map;

        map.stop();
        this._drainInertiaBuffer();
        this._inertia.push([Date.now(), pos]);

        map.transform.setLocationAtPoint(map.transform.pointLocation(this._pos), pos);

        this._fireEvent('drag', e);
        this._fireEvent('move', e);

        this._pos = pos;

        e.preventDefault();
    },

bug

All 13 comments

What are your thoughts, @bhousel?

The reason for wanting/needing to use dragPan.disable() mid-drag is that it is currently not possible to replicate the draggable marker functionality on touch devices.

On desktop, you can dragPan.disable() on mousemove (as per example) and lock the map prior to the drag event. On touch-devices, this is not possible, so the dragPan.disable() has to be called during the actual drag-event.

I identified more limitations (#2237) in the current interactions implementation a while back that probably, along with this, should be adressed in a broader re-design of how interactions are enabled/disabled and how interactions that depend on the state of others get such information...

should be adressed in a broader re-design of how interactions are enabled/disabled and how interactions that depend on the state of others get such information...

^ yes, this

Being able to disable interactions better would be nice. We are stepping around this in a few places with Draw currently. Mostly with zoom on double click.

@bhousel I'd love to see a clean-slate reimagining of our interaction handlers, when you have some spare cycles 馃槃

I got this error when app is in background and i am trying to open the app again ,i search a lot and get solution to disable map ,i tried this mapView.setEnabled(false); but unfortunately that's not working Anyone can help me to resolve this issue:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.orbis, PID: 15833
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.mapbox.mapboxsdk.maps.NativeMapView.createSurface(android.view.Surface)' on a null object reference
at com.mapbox.mapboxsdk.maps.MapView$SurfaceCallback.surfaceCreated(MapView.java:426)
at android.view.SurfaceView.updateWindow(SurfaceView.java:656)
at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:266)
at android.view.View.dispatchWindowVisibilityChanged(View.java:11139)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1855)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1550)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7190)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:959)
at android.view.Choreographer.doCallbacks(Choreographer.java:734)
at android.view.Choreographer.doFrame(Choreographer.java:670)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:945)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)

+1 I'm running into the same exact issue as @kristfal (disabling dragPan mid-drag for mobile/touch devices). It is a crucial functionality for my app.
Is there any progress on this?

I've created a pull request that fixes this issue.

@clemishow Agreed, this PR has been dead for a while! Can we get an owner to look at it again and help us get it accepted?

@krabbypattified Yeah, and in addition it works perfectly

This solved my problem.

map.on("mousemove", e => {
        var features = map.queryRenderedFeatures(e.point);
        if (features.length > 0) {
            if (hoveredStateId) {
                map.dragPan.disable();
                map.setFeatureState(
                    { source: 'states', id: hoveredStateId },
                    { hover: false }
                );
            }
                hoveredStateId = e.features[0].id;
                map.setFeatureState(
                { source: 'states', id: hoveredStateId },
                { hover: true }
            );
        }
    });

map.on("mouseleave", e => { var features = map.queryRenderedFeatures(e.point); if (features.length > 0) { map.dragPan.enable(); } });

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aendrew picture aendrew  路  3Comments

iamdenny picture iamdenny  路  3Comments

aderaaij picture aderaaij  路  3Comments

muesliq picture muesliq  路  3Comments

mollymerp picture mollymerp  路  3Comments