Add touchstart fallback and adjust interaction lockout
Introduce `touchstart` event listener as a fallback for older browsers lacking Pointer Events, and reduce the interaction lockout timer from 220ms to 150ms to prevent accidental orbit drags after a slap. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 418bf6f8-212b-4bb0-a7a5-8231a061da4e Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: b1d20c43-904b-495f-9262-401975d950d3 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/9f85e954-647c-46a5-90a7-396e495a805a/418bf6f8-212b-4bb0-a7a5-8231a061da4e/Q83Uqvu Replit-Helium-Checkpoint-Created: true
This commit is contained in:
@@ -39,27 +39,47 @@ export function initInteraction(camera, renderer) {
|
||||
// Capture phase so we intercept before OrbitControls' bubble-phase handler.
|
||||
// If Timmy is hit we call stopImmediatePropagation() to suppress the orbit drag.
|
||||
_canvas.addEventListener('pointerdown', _onPointerDown, { capture: true });
|
||||
|
||||
// touchstart fallback for older mobile browsers that lack Pointer Events
|
||||
if (!window.PointerEvent) {
|
||||
_canvas.addEventListener('touchstart', _onTouchStart, { capture: true, passive: false });
|
||||
}
|
||||
}
|
||||
|
||||
function _onPointerDown(event) {
|
||||
if (!_timmyGroup || !_applySlap || !_camera) return;
|
||||
function _hitTest(clientX, clientY) {
|
||||
if (!_timmyGroup || !_applySlap || !_camera) return false;
|
||||
|
||||
const rect = _canvas.getBoundingClientRect();
|
||||
_pointer.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
||||
_pointer.y = ((event.clientY - rect.top) / rect.height) * -2 + 1;
|
||||
_pointer.x = ((clientX - rect.left) / rect.width) * 2 - 1;
|
||||
_pointer.y = ((clientY - rect.top) / rect.height) * -2 + 1;
|
||||
|
||||
_raycaster.setFromCamera(_pointer, _camera);
|
||||
const hits = _raycaster.intersectObject(_timmyGroup, true);
|
||||
|
||||
if (hits.length > 0) {
|
||||
event.stopImmediatePropagation(); // block OrbitControls drag
|
||||
_applySlap(hits[0].point);
|
||||
|
||||
// Re-enable orbit after a short pause to avoid accidental rotation
|
||||
// 150 ms lockout to avoid accidental orbit drag immediately after a slap
|
||||
if (controls) {
|
||||
controls.enabled = false;
|
||||
setTimeout(() => { if (controls) controls.enabled = true; }, 220);
|
||||
setTimeout(() => { if (controls) controls.enabled = true; }, 150);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function _onPointerDown(event) {
|
||||
if (_hitTest(event.clientX, event.clientY)) {
|
||||
event.stopImmediatePropagation(); // block OrbitControls drag
|
||||
}
|
||||
}
|
||||
|
||||
function _onTouchStart(event) {
|
||||
if (!event.touches || event.touches.length === 0) return;
|
||||
const t = event.touches[0];
|
||||
if (_hitTest(t.clientX, t.clientY)) {
|
||||
event.stopImmediatePropagation();
|
||||
event.preventDefault(); // suppress subsequent mouse events (ghost click)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +95,9 @@ export function disposeInteraction() {
|
||||
if (_canvas) {
|
||||
_canvas.removeEventListener('contextmenu', _noCtxMenu);
|
||||
_canvas.removeEventListener('pointerdown', _onPointerDown, { capture: true });
|
||||
if (!window.PointerEvent) {
|
||||
_canvas.removeEventListener('touchstart', _onTouchStart, { capture: true });
|
||||
}
|
||||
_canvas = null;
|
||||
}
|
||||
if (controls) {
|
||||
|
||||
Reference in New Issue
Block a user