| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140 | import AssociativeArray from "./AssociativeArray.js";import Cartesian2 from "./Cartesian2.js";import defaultValue from "./defaultValue.js";import defined from "./defined.js";import destroyObject from "./destroyObject.js";import DeveloperError from "./DeveloperError.js";import FeatureDetection from "./FeatureDetection.js";import getTimestamp from "./getTimestamp.js";import KeyboardEventModifier from "./KeyboardEventModifier.js";import ScreenSpaceEventType from "./ScreenSpaceEventType.js";function getPosition(screenSpaceEventHandler, event, result) {  const element = screenSpaceEventHandler._element;  if (element === document) {    result.x = event.clientX;    result.y = event.clientY;    return result;  }  const rect = element.getBoundingClientRect();  result.x = event.clientX - rect.left;  result.y = event.clientY - rect.top;  return result;}function getInputEventKey(type, modifier) {  let key = type;  if (defined(modifier)) {    key += `+${modifier}`;  }  return key;}function getModifier(event) {  if (event.shiftKey) {    return KeyboardEventModifier.SHIFT;  } else if (event.ctrlKey) {    return KeyboardEventModifier.CTRL;  } else if (event.altKey) {    return KeyboardEventModifier.ALT;  }  return undefined;}const MouseButton = {  LEFT: 0,  MIDDLE: 1,  RIGHT: 2,};function registerListener(screenSpaceEventHandler, domType, element, callback) {  function listener(e) {    callback(screenSpaceEventHandler, e);  }  if (FeatureDetection.isInternetExplorer()) {    element.addEventListener(domType, listener, false);  } else {    element.addEventListener(domType, listener, {      capture: false,      passive: false,    });  }  screenSpaceEventHandler._removalFunctions.push(function () {    element.removeEventListener(domType, listener, false);  });}function registerListeners(screenSpaceEventHandler) {  const element = screenSpaceEventHandler._element;  // some listeners may be registered on the document, so we still get events even after  // leaving the bounds of element.  // this is affected by the existence of an undocumented disableRootEvents property on element.  const alternateElement = !defined(element.disableRootEvents)    ? document    : element;  if (FeatureDetection.supportsPointerEvents()) {    registerListener(      screenSpaceEventHandler,      "pointerdown",      element,      handlePointerDown    );    registerListener(      screenSpaceEventHandler,      "pointerup",      element,      handlePointerUp    );    registerListener(      screenSpaceEventHandler,      "pointermove",      element,      handlePointerMove    );    registerListener(      screenSpaceEventHandler,      "pointercancel",      element,      handlePointerUp    );  } else {    registerListener(      screenSpaceEventHandler,      "mousedown",      element,      handleMouseDown    );    registerListener(      screenSpaceEventHandler,      "mouseup",      alternateElement,      handleMouseUp    );    registerListener(      screenSpaceEventHandler,      "mousemove",      alternateElement,      handleMouseMove    );    registerListener(      screenSpaceEventHandler,      "touchstart",      element,      handleTouchStart    );    registerListener(      screenSpaceEventHandler,      "touchend",      alternateElement,      handleTouchEnd    );    registerListener(      screenSpaceEventHandler,      "touchmove",      alternateElement,      handleTouchMove    );    registerListener(      screenSpaceEventHandler,      "touchcancel",      alternateElement,      handleTouchEnd    );  }  registerListener(    screenSpaceEventHandler,    "dblclick",    element,    handleDblClick  );  // detect available wheel event  let wheelEvent;  if ("onwheel" in element) {    // spec event type    wheelEvent = "wheel";  } else if (document.onmousewheel !== undefined) {    // legacy event type    wheelEvent = "mousewheel";  } else {    // older Firefox    wheelEvent = "DOMMouseScroll";  }  registerListener(screenSpaceEventHandler, wheelEvent, element, handleWheel);}function unregisterListeners(screenSpaceEventHandler) {  const removalFunctions = screenSpaceEventHandler._removalFunctions;  for (let i = 0; i < removalFunctions.length; ++i) {    removalFunctions[i]();  }}const mouseDownEvent = {  position: new Cartesian2(),};function gotTouchEvent(screenSpaceEventHandler) {  screenSpaceEventHandler._lastSeenTouchEvent = getTimestamp();}function canProcessMouseEvent(screenSpaceEventHandler) {  return (    getTimestamp() - screenSpaceEventHandler._lastSeenTouchEvent >    ScreenSpaceEventHandler.mouseEmulationIgnoreMilliseconds  );}function checkPixelTolerance(startPosition, endPosition, pixelTolerance) {  const xDiff = startPosition.x - endPosition.x;  const yDiff = startPosition.y - endPosition.y;  const totalPixels = Math.sqrt(xDiff * xDiff + yDiff * yDiff);  return totalPixels < pixelTolerance;}function handleMouseDown(screenSpaceEventHandler, event) {  if (!canProcessMouseEvent(screenSpaceEventHandler)) {    return;  }  const button = event.button;  screenSpaceEventHandler._buttonDown[button] = true;  let screenSpaceEventType;  if (button === MouseButton.LEFT) {    screenSpaceEventType = ScreenSpaceEventType.LEFT_DOWN;  } else if (button === MouseButton.MIDDLE) {    screenSpaceEventType = ScreenSpaceEventType.MIDDLE_DOWN;  } else if (button === MouseButton.RIGHT) {    screenSpaceEventType = ScreenSpaceEventType.RIGHT_DOWN;  } else {    return;  }  const position = getPosition(    screenSpaceEventHandler,    event,    screenSpaceEventHandler._primaryPosition  );  Cartesian2.clone(position, screenSpaceEventHandler._primaryStartPosition);  Cartesian2.clone(position, screenSpaceEventHandler._primaryPreviousPosition);  const modifier = getModifier(event);  const action = screenSpaceEventHandler.getInputAction(    screenSpaceEventType,    modifier  );  if (defined(action)) {    Cartesian2.clone(position, mouseDownEvent.position);    action(mouseDownEvent);    event.preventDefault();  }}const mouseUpEvent = {  position: new Cartesian2(),};const mouseClickEvent = {  position: new Cartesian2(),};function cancelMouseEvent(  screenSpaceEventHandler,  screenSpaceEventType,  clickScreenSpaceEventType,  event) {  const modifier = getModifier(event);  const action = screenSpaceEventHandler.getInputAction(    screenSpaceEventType,    modifier  );  const clickAction = screenSpaceEventHandler.getInputAction(    clickScreenSpaceEventType,    modifier  );  if (defined(action) || defined(clickAction)) {    const position = getPosition(      screenSpaceEventHandler,      event,      screenSpaceEventHandler._primaryPosition    );    if (defined(action)) {      Cartesian2.clone(position, mouseUpEvent.position);      action(mouseUpEvent);    }    if (defined(clickAction)) {      const startPosition = screenSpaceEventHandler._primaryStartPosition;      if (        checkPixelTolerance(          startPosition,          position,          screenSpaceEventHandler._clickPixelTolerance        )      ) {        Cartesian2.clone(position, mouseClickEvent.position);        clickAction(mouseClickEvent);      }    }  }}function handleMouseUp(screenSpaceEventHandler, event) {  if (!canProcessMouseEvent(screenSpaceEventHandler)) {    return;  }  const button = event.button;  if (    button !== MouseButton.LEFT &&    button !== MouseButton.MIDDLE &&    button !== MouseButton.RIGHT  ) {    return;  }  if (screenSpaceEventHandler._buttonDown[MouseButton.LEFT]) {    cancelMouseEvent(      screenSpaceEventHandler,      ScreenSpaceEventType.LEFT_UP,      ScreenSpaceEventType.LEFT_CLICK,      event    );    screenSpaceEventHandler._buttonDown[MouseButton.LEFT] = false;  }  if (screenSpaceEventHandler._buttonDown[MouseButton.MIDDLE]) {    cancelMouseEvent(      screenSpaceEventHandler,      ScreenSpaceEventType.MIDDLE_UP,      ScreenSpaceEventType.MIDDLE_CLICK,      event    );    screenSpaceEventHandler._buttonDown[MouseButton.MIDDLE] = false;  }  if (screenSpaceEventHandler._buttonDown[MouseButton.RIGHT]) {    cancelMouseEvent(      screenSpaceEventHandler,      ScreenSpaceEventType.RIGHT_UP,      ScreenSpaceEventType.RIGHT_CLICK,      event    );    screenSpaceEventHandler._buttonDown[MouseButton.RIGHT] = false;  }}const mouseMoveEvent = {  startPosition: new Cartesian2(),  endPosition: new Cartesian2(),};function handleMouseMove(screenSpaceEventHandler, event) {  if (!canProcessMouseEvent(screenSpaceEventHandler)) {    return;  }  const modifier = getModifier(event);  const position = getPosition(    screenSpaceEventHandler,    event,    screenSpaceEventHandler._primaryPosition  );  const previousPosition = screenSpaceEventHandler._primaryPreviousPosition;  const action = screenSpaceEventHandler.getInputAction(    ScreenSpaceEventType.MOUSE_MOVE,    modifier  );  if (defined(action)) {    Cartesian2.clone(previousPosition, mouseMoveEvent.startPosition);    Cartesian2.clone(position, mouseMoveEvent.endPosition);    action(mouseMoveEvent);  }  Cartesian2.clone(position, previousPosition);  if (    screenSpaceEventHandler._buttonDown[MouseButton.LEFT] ||    screenSpaceEventHandler._buttonDown[MouseButton.MIDDLE] ||    screenSpaceEventHandler._buttonDown[MouseButton.RIGHT]  ) {    event.preventDefault();  }}const mouseDblClickEvent = {  position: new Cartesian2(),};function handleDblClick(screenSpaceEventHandler, event) {  const button = event.button;  let screenSpaceEventType;  if (button === MouseButton.LEFT) {    screenSpaceEventType = ScreenSpaceEventType.LEFT_DOUBLE_CLICK;  } else {    return;  }  const modifier = getModifier(event);  const action = screenSpaceEventHandler.getInputAction(    screenSpaceEventType,    modifier  );  if (defined(action)) {    getPosition(screenSpaceEventHandler, event, mouseDblClickEvent.position);    action(mouseDblClickEvent);  }}function handleWheel(screenSpaceEventHandler, event) {  // currently this event exposes the delta value in terms of  // the obsolete mousewheel event type.  so, for now, we adapt the other  // values to that scheme.  let delta;  // standard wheel event uses deltaY.  sign is opposite wheelDelta.  // deltaMode indicates what unit it is in.  if (defined(event.deltaY)) {    const deltaMode = event.deltaMode;    if (deltaMode === event.DOM_DELTA_PIXEL) {      delta = -event.deltaY;    } else if (deltaMode === event.DOM_DELTA_LINE) {      delta = -event.deltaY * 40;    } else {      // DOM_DELTA_PAGE      delta = -event.deltaY * 120;    }  } else if (event.detail > 0) {    // old Firefox versions use event.detail to count the number of clicks. The sign    // of the integer is the direction the wheel is scrolled.    delta = event.detail * -120;  } else {    delta = event.wheelDelta;  }  if (!defined(delta)) {    return;  }  const modifier = getModifier(event);  const action = screenSpaceEventHandler.getInputAction(    ScreenSpaceEventType.WHEEL,    modifier  );  if (defined(action)) {    action(delta);    event.preventDefault();  }}function handleTouchStart(screenSpaceEventHandler, event) {  gotTouchEvent(screenSpaceEventHandler);  const changedTouches = event.changedTouches;  let i;  const length = changedTouches.length;  let touch;  let identifier;  const positions = screenSpaceEventHandler._positions;  for (i = 0; i < length; ++i) {    touch = changedTouches[i];    identifier = touch.identifier;    positions.set(      identifier,      getPosition(screenSpaceEventHandler, touch, new Cartesian2())    );  }  fireTouchEvents(screenSpaceEventHandler, event);  const previousPositions = screenSpaceEventHandler._previousPositions;  for (i = 0; i < length; ++i) {    touch = changedTouches[i];    identifier = touch.identifier;    previousPositions.set(      identifier,      Cartesian2.clone(positions.get(identifier))    );  }}function handleTouchEnd(screenSpaceEventHandler, event) {  gotTouchEvent(screenSpaceEventHandler);  const changedTouches = event.changedTouches;  let i;  const length = changedTouches.length;  let touch;  let identifier;  const positions = screenSpaceEventHandler._positions;  for (i = 0; i < length; ++i) {    touch = changedTouches[i];    identifier = touch.identifier;    positions.remove(identifier);  }  fireTouchEvents(screenSpaceEventHandler, event);  const previousPositions = screenSpaceEventHandler._previousPositions;  for (i = 0; i < length; ++i) {    touch = changedTouches[i];    identifier = touch.identifier;    previousPositions.remove(identifier);  }}const touchStartEvent = {  position: new Cartesian2(),};const touch2StartEvent = {  position1: new Cartesian2(),  position2: new Cartesian2(),};const touchEndEvent = {  position: new Cartesian2(),};const touchClickEvent = {  position: new Cartesian2(),};const touchHoldEvent = {  position: new Cartesian2(),};function fireTouchEvents(screenSpaceEventHandler, event) {  const modifier = getModifier(event);  const positions = screenSpaceEventHandler._positions;  const numberOfTouches = positions.length;  let action;  let clickAction;  const pinching = screenSpaceEventHandler._isPinching;  if (    numberOfTouches !== 1 &&    screenSpaceEventHandler._buttonDown[MouseButton.LEFT]  ) {    // transitioning from single touch, trigger UP and might trigger CLICK    screenSpaceEventHandler._buttonDown[MouseButton.LEFT] = false;    if (defined(screenSpaceEventHandler._touchHoldTimer)) {      clearTimeout(screenSpaceEventHandler._touchHoldTimer);      screenSpaceEventHandler._touchHoldTimer = undefined;    }    action = screenSpaceEventHandler.getInputAction(      ScreenSpaceEventType.LEFT_UP,      modifier    );    if (defined(action)) {      Cartesian2.clone(        screenSpaceEventHandler._primaryPosition,        touchEndEvent.position      );      action(touchEndEvent);    }    if (numberOfTouches === 0 && !screenSpaceEventHandler._isTouchHolding) {      // releasing single touch, check for CLICK      clickAction = screenSpaceEventHandler.getInputAction(        ScreenSpaceEventType.LEFT_CLICK,        modifier      );      if (defined(clickAction)) {        const startPosition = screenSpaceEventHandler._primaryStartPosition;        const endPosition =          screenSpaceEventHandler._previousPositions.values[0];        if (          checkPixelTolerance(            startPosition,            endPosition,            screenSpaceEventHandler._clickPixelTolerance          )        ) {          Cartesian2.clone(            screenSpaceEventHandler._primaryPosition,            touchClickEvent.position          );          clickAction(touchClickEvent);        }      }    }    screenSpaceEventHandler._isTouchHolding = false;    // Otherwise don't trigger CLICK, because we are adding more touches.  }  if (numberOfTouches === 0 && pinching) {    // transitioning from pinch, trigger PINCH_END    screenSpaceEventHandler._isPinching = false;    action = screenSpaceEventHandler.getInputAction(      ScreenSpaceEventType.PINCH_END,      modifier    );    if (defined(action)) {      action();    }  }  if (numberOfTouches === 1 && !pinching) {    // transitioning to single touch, trigger DOWN    const position = positions.values[0];    Cartesian2.clone(position, screenSpaceEventHandler._primaryPosition);    Cartesian2.clone(position, screenSpaceEventHandler._primaryStartPosition);    Cartesian2.clone(      position,      screenSpaceEventHandler._primaryPreviousPosition    );    screenSpaceEventHandler._buttonDown[MouseButton.LEFT] = true;    action = screenSpaceEventHandler.getInputAction(      ScreenSpaceEventType.LEFT_DOWN,      modifier    );    if (defined(action)) {      Cartesian2.clone(position, touchStartEvent.position);      action(touchStartEvent);    }    screenSpaceEventHandler._touchHoldTimer = setTimeout(function () {      if (!screenSpaceEventHandler.isDestroyed()) {        screenSpaceEventHandler._touchHoldTimer = undefined;        screenSpaceEventHandler._isTouchHolding = true;        clickAction = screenSpaceEventHandler.getInputAction(          ScreenSpaceEventType.RIGHT_CLICK,          modifier        );        if (defined(clickAction)) {          const startPosition = screenSpaceEventHandler._primaryStartPosition;          const endPosition =            screenSpaceEventHandler._previousPositions.values[0];          if (            checkPixelTolerance(              startPosition,              endPosition,              screenSpaceEventHandler._holdPixelTolerance            )          ) {            Cartesian2.clone(              screenSpaceEventHandler._primaryPosition,              touchHoldEvent.position            );            clickAction(touchHoldEvent);          }        }      }    }, ScreenSpaceEventHandler.touchHoldDelayMilliseconds);    event.preventDefault();  }  if (numberOfTouches === 2 && !pinching) {    // transitioning to pinch, trigger PINCH_START    screenSpaceEventHandler._isPinching = true;    action = screenSpaceEventHandler.getInputAction(      ScreenSpaceEventType.PINCH_START,      modifier    );    if (defined(action)) {      Cartesian2.clone(positions.values[0], touch2StartEvent.position1);      Cartesian2.clone(positions.values[1], touch2StartEvent.position2);      action(touch2StartEvent);      // Touch-enabled devices, in particular iOS can have many default behaviours for      // "pinch" events, which can still be executed unless we prevent them here.      event.preventDefault();    }  }}function handleTouchMove(screenSpaceEventHandler, event) {  gotTouchEvent(screenSpaceEventHandler);  const changedTouches = event.changedTouches;  let i;  const length = changedTouches.length;  let touch;  let identifier;  const positions = screenSpaceEventHandler._positions;  for (i = 0; i < length; ++i) {    touch = changedTouches[i];    identifier = touch.identifier;    const position = positions.get(identifier);    if (defined(position)) {      getPosition(screenSpaceEventHandler, touch, position);    }  }  fireTouchMoveEvents(screenSpaceEventHandler, event);  const previousPositions = screenSpaceEventHandler._previousPositions;  for (i = 0; i < length; ++i) {    touch = changedTouches[i];    identifier = touch.identifier;    Cartesian2.clone(      positions.get(identifier),      previousPositions.get(identifier)    );  }}const touchMoveEvent = {  startPosition: new Cartesian2(),  endPosition: new Cartesian2(),};const touchPinchMovementEvent = {  distance: {    startPosition: new Cartesian2(),    endPosition: new Cartesian2(),  },  angleAndHeight: {    startPosition: new Cartesian2(),    endPosition: new Cartesian2(),  },};function fireTouchMoveEvents(screenSpaceEventHandler, event) {  const modifier = getModifier(event);  const positions = screenSpaceEventHandler._positions;  const previousPositions = screenSpaceEventHandler._previousPositions;  const numberOfTouches = positions.length;  let action;  if (    numberOfTouches === 1 &&    screenSpaceEventHandler._buttonDown[MouseButton.LEFT]  ) {    // moving single touch    const position = positions.values[0];    Cartesian2.clone(position, screenSpaceEventHandler._primaryPosition);    const previousPosition = screenSpaceEventHandler._primaryPreviousPosition;    action = screenSpaceEventHandler.getInputAction(      ScreenSpaceEventType.MOUSE_MOVE,      modifier    );    if (defined(action)) {      Cartesian2.clone(previousPosition, touchMoveEvent.startPosition);      Cartesian2.clone(position, touchMoveEvent.endPosition);      action(touchMoveEvent);    }    Cartesian2.clone(position, previousPosition);    event.preventDefault();  } else if (numberOfTouches === 2 && screenSpaceEventHandler._isPinching) {    // moving pinch    action = screenSpaceEventHandler.getInputAction(      ScreenSpaceEventType.PINCH_MOVE,      modifier    );    if (defined(action)) {      const position1 = positions.values[0];      const position2 = positions.values[1];      const previousPosition1 = previousPositions.values[0];      const previousPosition2 = previousPositions.values[1];      const dX = position2.x - position1.x;      const dY = position2.y - position1.y;      const dist = Math.sqrt(dX * dX + dY * dY) * 0.25;      const prevDX = previousPosition2.x - previousPosition1.x;      const prevDY = previousPosition2.y - previousPosition1.y;      const prevDist = Math.sqrt(prevDX * prevDX + prevDY * prevDY) * 0.25;      const cY = (position2.y + position1.y) * 0.125;      const prevCY = (previousPosition2.y + previousPosition1.y) * 0.125;      const angle = Math.atan2(dY, dX);      const prevAngle = Math.atan2(prevDY, prevDX);      Cartesian2.fromElements(        0.0,        prevDist,        touchPinchMovementEvent.distance.startPosition      );      Cartesian2.fromElements(        0.0,        dist,        touchPinchMovementEvent.distance.endPosition      );      Cartesian2.fromElements(        prevAngle,        prevCY,        touchPinchMovementEvent.angleAndHeight.startPosition      );      Cartesian2.fromElements(        angle,        cY,        touchPinchMovementEvent.angleAndHeight.endPosition      );      action(touchPinchMovementEvent);    }  }}function handlePointerDown(screenSpaceEventHandler, event) {  event.target.setPointerCapture(event.pointerId);  if (event.pointerType === "touch") {    const positions = screenSpaceEventHandler._positions;    const identifier = event.pointerId;    positions.set(      identifier,      getPosition(screenSpaceEventHandler, event, new Cartesian2())    );    fireTouchEvents(screenSpaceEventHandler, event);    const previousPositions = screenSpaceEventHandler._previousPositions;    previousPositions.set(      identifier,      Cartesian2.clone(positions.get(identifier))    );  } else {    handleMouseDown(screenSpaceEventHandler, event);  }}function handlePointerUp(screenSpaceEventHandler, event) {  if (event.pointerType === "touch") {    const positions = screenSpaceEventHandler._positions;    const identifier = event.pointerId;    positions.remove(identifier);    fireTouchEvents(screenSpaceEventHandler, event);    const previousPositions = screenSpaceEventHandler._previousPositions;    previousPositions.remove(identifier);  } else {    handleMouseUp(screenSpaceEventHandler, event);  }}function handlePointerMove(screenSpaceEventHandler, event) {  if (event.pointerType === "touch") {    const positions = screenSpaceEventHandler._positions;    const identifier = event.pointerId;    const position = positions.get(identifier);    if (!defined(position)) {      return;    }    getPosition(screenSpaceEventHandler, event, position);    fireTouchMoveEvents(screenSpaceEventHandler, event);    const previousPositions = screenSpaceEventHandler._previousPositions;    Cartesian2.clone(      positions.get(identifier),      previousPositions.get(identifier)    );  } else {    handleMouseMove(screenSpaceEventHandler, event);  }}/** * @typedef {Object} ScreenSpaceEventHandler.PositionedEvent * * An Event that occurs at a single position on screen. * * @property {Cartesian2} position *//** * @callback ScreenSpaceEventHandler.PositionedEventCallback * * The callback invoked when a positioned event triggers an event listener. * * @param {ScreenSpaceEventHandler.PositionedEvent} event The event which triggered the listener *//** * @typedef {Object} ScreenSpaceEventHandler.MotionEvent * * An Event that starts at one position and ends at another. * * @property {Cartesian2} startPosition * @property {Cartesian2} endPosition *//** * @callback ScreenSpaceEventHandler.MotionEventCallback * * The callback invoked when a motion event triggers an event listener. * * @param {ScreenSpaceEventHandler.MotionEvent} event The event which triggered the listener *//** * @typedef {Object} ScreenSpaceEventHandler.TwoPointEvent * * An Event that occurs at a two positions on screen. * * @property {Cartesian2} position1 * @property {Cartesian2} position2 *//** * @callback ScreenSpaceEventHandler.TwoPointEventCallback * * The callback invoked when a two-point event triggers an event listener. * * @param {ScreenSpaceEventHandler.TwoPointEvent} event The event which triggered the listener *//** * @typedef {Object} ScreenSpaceEventHandler.TwoPointMotionEvent * * An Event that starts at a two positions on screen and moves to two other positions. * * @property {Cartesian2} position1 * @property {Cartesian2} position2 * @property {Cartesian2} previousPosition1 * @property {Cartesian2} previousPosition2 *//** * @callback ScreenSpaceEventHandler.TwoPointMotionEventCallback * * The callback invoked when a two-point motion event triggers an event listener. * * @param {ScreenSpaceEventHandler.TwoPointMotionEvent} event The event which triggered the listener *//** * @callback ScreenSpaceEventHandler.WheelEventCallback * * The callback invoked when a mouse-wheel event triggers an event listener. * * @param {number} delta The amount that the mouse wheel moved *//** * Handles user input events. Custom functions can be added to be executed on * when the user enters input. * * @alias ScreenSpaceEventHandler * * @param {HTMLCanvasElement} [element=document] The element to add events to. * * @constructor */function ScreenSpaceEventHandler(element) {  this._inputEvents = {};  this._buttonDown = {    LEFT: false,    MIDDLE: false,    RIGHT: false,  };  this._isPinching = false;  this._isTouchHolding = false;  this._lastSeenTouchEvent = -ScreenSpaceEventHandler.mouseEmulationIgnoreMilliseconds;  this._primaryStartPosition = new Cartesian2();  this._primaryPosition = new Cartesian2();  this._primaryPreviousPosition = new Cartesian2();  this._positions = new AssociativeArray();  this._previousPositions = new AssociativeArray();  this._removalFunctions = [];  this._touchHoldTimer = undefined;  // TODO: Revisit when doing mobile development. May need to be configurable  // or determined based on the platform?  this._clickPixelTolerance = 5;  this._holdPixelTolerance = 25;  this._element = defaultValue(element, document);  registerListeners(this);}/** * Set a function to be executed on an input event. * * @param {ScreenSpaceEventHandler.PositionedEventCallback|ScreenSpaceEventHandler.MotionEventCallback|ScreenSpaceEventHandler.WheelEventCallback|ScreenSpaceEventHandler.TwoPointEventCallback|ScreenSpaceEventHandler.TwoPointMotionEventCallback} action Function to be executed when the input event occurs. * @param {ScreenSpaceEventType} type The ScreenSpaceEventType of input event. * @param {KeyboardEventModifier} [modifier] A KeyboardEventModifier key that is held when a <code>type</code> * event occurs. * * @see ScreenSpaceEventHandler#getInputAction * @see ScreenSpaceEventHandler#removeInputAction */ScreenSpaceEventHandler.prototype.setInputAction = function (  action,  type,  modifier) {  //>>includeStart('debug', pragmas.debug);  if (!defined(action)) {    throw new DeveloperError("action is required.");  }  if (!defined(type)) {    throw new DeveloperError("type is required.");  }  //>>includeEnd('debug');  const key = getInputEventKey(type, modifier);  this._inputEvents[key] = action;};/** * Returns the function to be executed on an input event. * * @param {ScreenSpaceEventType} type The ScreenSpaceEventType of input event. * @param {KeyboardEventModifier} [modifier] A KeyboardEventModifier key that is held when a <code>type</code> * event occurs. * * @returns {ScreenSpaceEventHandler.PositionedEventCallback|ScreenSpaceEventHandler.MotionEventCallback|ScreenSpaceEventHandler.WheelEventCallback|ScreenSpaceEventHandler.TwoPointEventCallback|ScreenSpaceEventHandler.TwoPointMotionEventCallback} The function to be executed on an input event. * * @see ScreenSpaceEventHandler#setInputAction * @see ScreenSpaceEventHandler#removeInputAction */ScreenSpaceEventHandler.prototype.getInputAction = function (type, modifier) {  //>>includeStart('debug', pragmas.debug);  if (!defined(type)) {    throw new DeveloperError("type is required.");  }  //>>includeEnd('debug');  const key = getInputEventKey(type, modifier);  return this._inputEvents[key];};/** * Removes the function to be executed on an input event. * * @param {ScreenSpaceEventType} type The ScreenSpaceEventType of input event. * @param {KeyboardEventModifier} [modifier] A KeyboardEventModifier key that is held when a <code>type</code> * event occurs. * * @see ScreenSpaceEventHandler#getInputAction * @see ScreenSpaceEventHandler#setInputAction */ScreenSpaceEventHandler.prototype.removeInputAction = function (  type,  modifier) {  //>>includeStart('debug', pragmas.debug);  if (!defined(type)) {    throw new DeveloperError("type is required.");  }  //>>includeEnd('debug');  const key = getInputEventKey(type, modifier);  delete this._inputEvents[key];};/** * Returns true if this object was destroyed; otherwise, false. * <br /><br /> * If this object was destroyed, it should not be used; calling any function other than * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. * * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>. * * @see ScreenSpaceEventHandler#destroy */ScreenSpaceEventHandler.prototype.isDestroyed = function () {  return false;};/** * Removes listeners held by this object. * <br /><br /> * Once an object is destroyed, it should not be used; calling any function other than * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.  Therefore, * assign the return value (<code>undefined</code>) to the object as done in the example. * * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called. * * * @example * handler = handler && handler.destroy(); * * @see ScreenSpaceEventHandler#isDestroyed */ScreenSpaceEventHandler.prototype.destroy = function () {  unregisterListeners(this);  return destroyObject(this);};/** * The amount of time, in milliseconds, that mouse events will be disabled after * receiving any touch events, such that any emulated mouse events will be ignored. * @type {Number} * @default 800 */ScreenSpaceEventHandler.mouseEmulationIgnoreMilliseconds = 800;/** * The amount of time, in milliseconds, before a touch on the screen becomes a * touch and hold. * @type {Number} * @default 1500 */ScreenSpaceEventHandler.touchHoldDelayMilliseconds = 1500;export default ScreenSpaceEventHandler;
 |