Unintuitive touch events

I’ve been testing touch events recently, and I noticed that after a pinch-zoom event, a left click is sometimes triggered. After further investigation I discovered that events are triggered in the following sequence over the course of a pinch-zoom event:

  1. First touch on the screen - triggers left down event
  2. Second touch on the screen - triggers left up event (what?!)
  3. One touch removed from the screen - triggers left down event (why?! why?! WHY?!)
  4. Remaining touch removed from the screen - triggers left up event
    I’ve looked through the source code, and I understand what’s going on… but why?! It’s unintuitive.

I’m using this for a mapping tool that allows users to draw waypoints on a map. During drawing, if the user pinch-zooms into the map then a point may or may not be drawn in an undesirable place. I had to write a workaround in my code to prevent the left click occurring.

Hi Harry,

There’s a thread that discusses the rationale behind the events here.

For your purposes, it’s possible to bypass the ScreenSpaceEvents in Cesium and listen for the touch/click events from the browser directly.

Thanks,

Gabby

Hi Gabby,

Thanks for the link.

I’m doing this to bypass the ScreenSpaceEvents:

let pinchEnded = true;

const touchInfo: Array<{

touchId: number;

startPosition: { x: number; y: number };

}> = ;

const ngTouchstartHandler = renderer.listen(

this.mainMapViewer.canvas,

“touchstart”,

e => {

pinchEnded = e.touches.length <= 1;

// Capture touch info for every changed touch point on the screen

for (let i = 0; i < e.changedTouches.length; i++) {

const changedTouch = e.changedTouches.item(i);

touchInfo.push({

startPosition: {

x: changedTouch.clientX,

y: changedTouch.clientY

},

touchId: changedTouch.identifier

});

}

}

);

const ngTouchendHandler = renderer.listen(

this.mainMapViewer.canvas,

“touchend”,

e => {

// If all touches have been removed from the screen…

if (e.touches.length === 0) {

// …then check to see how far the changed touches had been moved before being removed from the screen

for (let i = 0; i < e.changedTouches.length; i++) {

const changedTouch = e.changedTouches.item(i);

const startPosition = _.find(

touchInfo,

x => x.touchId === changedTouch.identifier

).startPosition;

const endPosition = {

x: changedTouch.clientX,

y: changedTouch.clientY

};

const xDiff = startPosition.x - endPosition.x;

const yDiff = startPosition.y - endPosition.y;

const totalPixels = Math.sqrt(xDiff * xDiff + yDiff * yDiff);

// If the touches have moved a distance less than the tolerance then a LEFT_CLICK event will be fired

if (totalPixels < this.cesiumClickPixelTolerance) {

// So set this variable to false to prevent stuff being done in the LEFT_CLICK handler

pinchEnded = false;

}

}

}

}

);

cesiumClickHandler.setInputAction(click => {

if (pinchEnded) {

   // Do stuff...

}

pinchEnded = pinchEnded || true;

}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

It works pretty well.

Thanks,

Harry

Glad you got the events working for your purposes! Also thanks for the update with the code example!