openlayers / openlayers

OpenLayers
https://openlayers.org
BSD 2-Clause "Simplified" License
11.26k stars 3.02k forks source link

Multi-touch and single-touch interactions activating at the same time #14684

Open isti115 opened 1 year ago

isti115 commented 1 year ago

Describe the bug When a feature is selected while performing a multi-touch interaction, such as zooming or rotating the map, the selected feature sometimes also gets translated. See the following video for an illustration:

https://user-images.githubusercontent.com/3758493/232521975-7891f611-7c2b-47e1-936b-ff0869f551fb.mp4

(It seemed unlikely to me that nobody has encountered this so far, so I have checked the entire list of the 135 issues submitted so far that mention the keyword touch, but haven't found any reporting the same issue, maybe #9138 is related.)

To Reproduce Steps to reproduce the behavior:

  1. Go to Translate Features on a touch capable device.
  2. Select a feature on the map with a single tap.
  3. Perform a pinch to zoom interaction with the initial position of one of your fingers being above the selected feature.
  4. See the feature being translated and the map being zoomed at the same time.

Expected behavior As a user I would expect multi-touch interactions to take precedence over single-touch interactions, so in this case the feature should not be translated in my opinion while the zoom is being performed.

isti115 commented 1 year ago

I think that I have managed to identify the cause, but I'm not sure what the best approach would be towards mitigating the issue. The main problem seems to be that the propagation of drag events are never stopped. This makes sense, as drag events might need to be processed by multiple interactions, e.g. when pinch rotating and zooming at the same time, but this also leads to some undesirable outcomes.

One possible approach would be specifying the canonical order of the bundled multi-touch interactions and stopping the propagation of drag events in the "last" one as defined by this order. In this case the user could just disable the default list of interactions and add them back at the end of their custom list, so they would be able to catch the events, and filtering for touch count in each custom interaction wouldn't be necessary.

In this case the default implementation of the handleEvent method in PointerInteraction should also set stopEvent according to the value returned from handleDragEvent, which is currently completely discarded: https://github.com/openlayers/openlayers/blob/4fae13ebe9b87a07bc3338d425bd4029e08f9ccc/src/ol/interaction/Pointer.js#L133

Another approach could be adding a check like this at the beginning of the handleDragEvent implementation of single-touch interactions, such as Translate: https://github.com/openlayers/openlayers/blob/4fae13ebe9b87a07bc3338d425bd4029e08f9ccc/src/ol/interaction/Translate.js#L291

if (this.targetPointers.length > 1) {
  return;
}