src/viewer/scene/CameraControl/lib/handlers/TouchPickHandler.js
- import {math} from "../../../math/math.js";
-
- const TAP_INTERVAL = 150;
- const DBL_TAP_INTERVAL = 325;
- const TAP_DISTANCE_THRESHOLD = 4;
-
- const getCanvasPosFromEvent = function (event, canvasPos) {
- if (!event) {
- event = window.event;
- canvasPos[0] = event.x;
- canvasPos[1] = event.y;
- } else {
- let element = event.target;
- let totalOffsetLeft = 0;
- let totalOffsetTop = 0;
- while (element.offsetParent) {
- totalOffsetLeft += element.offsetLeft;
- totalOffsetTop += element.offsetTop;
- element = element.offsetParent;
- }
- canvasPos[0] = event.pageX - totalOffsetLeft;
- canvasPos[1] = event.pageY - totalOffsetTop;
- }
- return canvasPos;
- };
-
- /**
- * @private
- */
- class TouchPickHandler {
-
- constructor(scene, controllers, configs, states, updates) {
-
- this._scene = scene;
-
- const pickController = controllers.pickController;
- const cameraControl = controllers.cameraControl;
-
- let touchStartTime;
- const activeTouches = [];
- const tapStartPos = new Float32Array(2);
- let tapStartTime = -1;
- let lastTapTime = -1;
-
- const canvas = this._scene.canvas.canvas;
-
- const flyCameraTo = (pickResult) => {
- let pos;
- if (pickResult && pickResult.worldPos) {
- pos = pickResult.worldPos
- }
- const aabb = pickResult ? pickResult.entity.aabb : scene.aabb;
- if (pos) { // Fly to look at point, don't change eye->look dist
- const camera = scene.camera;
- const diff = math.subVec3(camera.eye, camera.look, []);
- controllers.cameraFlight.flyTo({
- aabb: aabb
- });
- // TODO: Option to back off to fit AABB in view
- } else {// Fly to fit target boundary in view
- controllers.cameraFlight.flyTo({
- aabb: aabb
- });
- }
- };
-
- canvas.addEventListener("touchstart", this._canvasTouchStartHandler = (e) => {
-
- if (!(configs.active && configs.pointerEnabled)) {
- return;
- }
-
- if (states.longTouchTimeout !== null) {
- clearTimeout(states.longTouchTimeout);
- states.longTouchTimeout = null;
- }
-
- const touches = e.touches;
- const changedTouches = e.changedTouches;
-
- touchStartTime = Date.now();
-
- if (touches.length === 1 && changedTouches.length === 1) {
- tapStartTime = touchStartTime;
-
- getCanvasPosFromEvent(touches[0], tapStartPos);
-
- const rightClickClientX = tapStartPos[0];
- const rightClickClientY = tapStartPos[1];
-
- const rightClickPageX = touches[0].pageX;
- const rightClickPageY = touches[0].pageY;
-
- states.longTouchTimeout = setTimeout(() => {
- controllers.cameraControl.fire("rightClick", { // For context menus
- pagePos: [Math.round(rightClickPageX), Math.round(rightClickPageY)],
- canvasPos: [Math.round(rightClickClientX), Math.round(rightClickClientY)],
- event: e
- }, true);
-
- states.longTouchTimeout = null;
- }, configs.longTapTimeout);
-
- } else {
- tapStartTime = -1;
- }
-
- while (activeTouches.length < touches.length) {
- activeTouches.push(new Float32Array(2))
- }
-
- for (let i = 0, len = touches.length; i < len; ++i) {
- getCanvasPosFromEvent(touches[i], activeTouches[i]);
- }
-
- activeTouches.length = touches.length;
-
- }, {passive: true});
-
-
- canvas.addEventListener("touchend", this._canvasTouchEndHandler = (e) => {
-
- if (!(configs.active && configs.pointerEnabled)) {
- return;
- }
-
- const currentTime = Date.now();
- const touches = e.touches;
- const changedTouches = e.changedTouches;
-
- const pickedSurfaceSubs = cameraControl.hasSubs("pickedSurface");
-
- if (states.longTouchTimeout !== null) {
- clearTimeout(states.longTouchTimeout);
- states.longTouchTimeout = null;
- }
-
- // process tap
-
- if (touches.length === 0 && changedTouches.length === 1) {
-
- if (tapStartTime > -1 && currentTime - tapStartTime < TAP_INTERVAL) {
-
- if (lastTapTime > -1 && tapStartTime - lastTapTime < DBL_TAP_INTERVAL) {
-
- // Double-tap
-
- getCanvasPosFromEvent(changedTouches[0], pickController.pickCursorPos);
- pickController.schedulePickEntity = true;
- pickController.schedulePickSurface = pickedSurfaceSubs;
-
- pickController.update();
-
- if (pickController.pickResult) {
-
- pickController.pickResult.touchInput = true;
-
- cameraControl.fire("doublePicked", pickController.pickResult);
-
- if (pickController.pickedSurface) {
- cameraControl.fire("doublePickedSurface", pickController.pickResult);
- }
-
- if (configs.doublePickFlyTo) {
- flyCameraTo(pickController.pickResult);
- }
- } else {
- cameraControl.fire("doublePickedNothing");
- if (configs.doublePickFlyTo) {
- flyCameraTo();
- }
- }
-
- lastTapTime = -1;
-
- } else if (math.distVec2(activeTouches[0], tapStartPos) < TAP_DISTANCE_THRESHOLD) {
-
- // Single-tap
-
- getCanvasPosFromEvent(changedTouches[0], pickController.pickCursorPos);
- pickController.schedulePickEntity = true;
- pickController.schedulePickSurface = pickedSurfaceSubs;
-
- pickController.update();
-
- if (pickController.pickResult) {
-
- pickController.pickResult.touchInput = true;
-
- cameraControl.fire("picked", pickController.pickResult);
-
- if (pickController.pickedSurface) {
- cameraControl.fire("pickedSurface", pickController.pickResult);
- }
-
- } else {
- cameraControl.fire("pickedNothing");
- }
-
- lastTapTime = currentTime;
- }
-
- tapStartTime = -1
- }
- }
-
- activeTouches.length = touches.length;
-
- for (let i = 0, len = touches.length; i < len; ++i) {
- activeTouches[i][0] = touches[i].pageX;
- activeTouches[i][1] = touches[i].pageY;
- }
-
- // e.stopPropagation();
-
- }, {passive: true});
-
- }
-
- reset() {
- // TODO
- // tapStartTime = -1;
- // lastTapTime = -1;
-
- }
-
- destroy() {
- const canvas = this._scene.canvas.canvas;
- canvas.removeEventListener("touchstart", this._canvasTouchStartHandler);
- canvas.removeEventListener("touchend", this._canvasTouchEndHandler);
- }
- }
-
-
- export {TouchPickHandler};