robtot
robtot

Reputation: 1031

OpenLayers 7: Dragging (dragpan-mode) stuck on left-mouse single-clicking the map

The dragging-mode (dragpan-mode) gets stuck when left-mouse single-clicking the map. I can't seem to cancel the dragging (dragpanning) in any way. Wherever my mouse moves, the map goes (without me holding any buttons down). I use Vue, but that should not matter. I also use OpenLayers v7, but I tried, and get the same issue on OpenLayers v6.

Map.vue

<template>
    <div id="map" ref="map" />
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import MapComponent from '@/map/MapComponent'
import "ol/ol.css"

const map = ref()

onMounted(async () => {
    await initiateMap()
})

function initiateMap() {
    map.value  = new MapComponent().getMap()
}

</script>

<style scoped>
#map {
    min-height: 0; /* Let the content overflow */
    flex: 1;       /* Fill the available space */
}
</style>

MapComponent.ts

import Map from 'ol/Map'
import View from 'ol/View'
import OSM from 'ol/source/OSM'
import TileLayer from 'ol/layer/Tile'
import { transform } from 'ol/proj'
import { defaults as interactionDefaults } from 'ol/interaction/defaults'
import { DragPan } from 'ol/interaction'

export default class MapComponent {

    map: any = null
   
    constructor() {
        this.createMap()
    }

    private createMap(): void {
        this.map = new Map({
            interactions: interactionDefaults({ 
                doubleClickZoom: false,
                altShiftDragRotate: false,
                dragPan: false,
                onFocusOnly: true,
                keyboard: false,
                mouseWheelZoom: false,
                shiftDragZoom: false,
                pinchRotate: false,
                pinchZoom: false        
            }).extend([
                new DragPan({
                    condition: function(event: any) {
                        console.log('event: ', event)
                        return event.originalEvent.button < 2
                    }
                })
            ]),
            layers: [
                new TileLayer({
                    source: new OSM(),
                }),
            ],
            view: new View({
                minZoom: 8,
                maxZoom: 20,
                zoomFactor: 2,
                center: transform([6, 50], 'EPSG:4326', 'EPSG:3857'),
                zoom: 2,
            }),
            target: "map"
        })

        this.addMapEvents()
    }

    public getMap() {
        return this.map
    }

    private addMapEvents(): void {
        this.map.on('click', () => console.log('left single click'))
        this.map.on('movestart', () => console.log('[M] Move start'))
        this.map.on('moveend', () => console.log('[M] Move end'))
        this.map.on('pointerdrag', () => console.log('[M] Pointer drag'))
        this.map.on('pointermove', () => console.log('[M] Pointer end'))
    }
}

Console log

[M] Move start
[M] Move end
(417)[M] Pointer end
event:  MapBrowserEvent {type: 'pointerdown', target: Map, map: Map, frameState: {…}, originalEvent: PointerEvent, …}
[M] Pointer end
[M] Pointer drag
[M] Pointer end
[M] Pointer drag
// Continued spam of Pointer end and Pointer drag
// Move start and end is never triggered again

It seems that if I adjust node_modules/ol/MapBrowserEventHandler.js and empty this.activePointers it works. This seems dangerous though:

  /**
   * @param {PointerEvent} pointerEvent Pointer
   * event.
   * @private
   */
  handlePointerUp_(pointerEvent) {
    this.updateActivePointers_(pointerEvent);
    const newEvent = new MapBrowserEvent(
      MapBrowserEventType.POINTERUP,
      this.map_,
      pointerEvent,
      undefined,
      undefined,
      this.activePointers_
    );
    this.dispatchEvent(newEvent);

    // We emulate click events on left mouse button click, touch contact, and pen
    // contact. isMouseActionButton returns true in these cases (evt.button is set
    // to 0).
    // See http://www.w3.org/TR/pointerevents/#button-states
    // We only fire click, singleclick, and doubleclick if nobody has called
    // event.preventDefault().
    if (
      this.emulateClicks_ &&
      !newEvent.defaultPrevented &&
      !this.dragging_ &&
      this.isMouseActionButton_(pointerEvent)
    ) {
      this.emulateClick_(this.down_);
    } else {
      this.activePointers_ = [] // Added
    }

    if (this.activePointers_.length === 0) {
      this.dragListenerKeys_.forEach(unlistenByKey);
      this.dragListenerKeys_.length = 0;
      this.dragging_ = false;
      this.down_ = null;
    }
  }

Above adjustments were inspired from the following Draw Interaction result not showing with stopClick and quick double click to close

Upvotes: 0

Views: 344

Answers (1)

Philippe Duchesne
Philippe Duchesne

Reputation: 1

To anyone still hitting this problem, it appears to be related to a combination of certain versions of VM, OS and Chrome : https://github.com/openlayers/openlayers/issues/12934

In a nutshell, under these conditions, the browser sends erroneous events where the mousedown event is attributed to the mouse, but the mouseup is attributed to some pen device. As a result, openlayers does not release the drag behaviour.

Upvotes: 0

Related Questions