message: TouchCaptor should only update hasMoved after an actual move
  It seems some browsers (notably chrome) tend to emit zero-distance events, thus failing our hasMoved heuristic.
diff: @@ -39,7 +39,7 @@ export default class TouchCaptor extends Captor<TouchCaptorEvents> {
  startTouchesAngle?: number;
  startTouchesDistance?: number;
  - startTouchesPositions?: Coordinates[];
  + startTouchesPositions: Coordinates[] = [];
  lastTouchesPositions?: Coordinates[];
  lastTouches?: Touch[];
  @@ -163,12 +163,12 @@ export default class TouchCaptor extends Captor<TouchCaptorEvents> {
  );
  }
  + this.hasMoved = false;
  this.isMoving = false;
  this.touchMode = 0;
  break;
  }
  - this.hasMoved = false;
  this.emit("touchup", getTouchCoords(e, this.container));
  }
  @@ -180,14 +180,29 @@ export default class TouchCaptor extends Captor<TouchCaptorEvents> {
  // ...but simulate mouse behavior anyway, to get the MouseCaptor working as well:
  if (e.touches.length === 1) this.dispatchRelatedMouseEvent("mousemove", e);
  - const camera = this.renderer.getCamera();
  - const startCameraState = this.startCameraState as CameraState;
  const touches = getTouchesArray(e.touches);
  const touchesPositions = touches.map((touch) => getPosition(touch, this.container));
  this.lastTouches = touches;
  this.lastTouchesPositions = touchesPositions;
  +
  + // If a move was initiated at some point and we get back to startpoint,
  + // we should still consider that we did move (which also happens after a
  + // multiple touch when only one touch remains in which case handleStart
  + // is recalled within handleLeave).
  + // Now, some mobile browsers report zero-distance moves so we also check that
  + // one of the touches did actually move from the origin position.
  + this.hasMoved ||= touchesPositions.some((position, idx) => {
  + const startPosition = this.startTouchesPositions[idx];
  +
  + return position.x !== startPosition.x || position.y !== startPosition.y;
  + });
  +
  + // If there was no move, do not trigger touch moves behavior
  + if (!this.hasMoved) {
  + return;
  + }
  +
  this.isMoving = true;
  - this.hasMoved = true;
  if (this.movingTimeout) clearTimeout(this.movingTimeout);
  @@ -195,6 +210,9 @@ export default class TouchCaptor extends Captor<TouchCaptorEvents> {
  this.isMoving = false;
  }, DRAG_TIMEOUT);
  + const camera = this.renderer.getCamera();
  + const startCameraState = this.startCameraState as CameraState;
  +
  switch (this.touchMode) {
  case 1: {
  const { x: xStart, y: yStart } = this.renderer.viewportToFramedGraph(
  