From eef1e3a7890fca451401a4ef295cd7665e78bf92 Mon Sep 17 00:00:00 2001 From: seb Date: Mon, 25 Aug 2025 06:14:34 +0200 Subject: [PATCH] u --- src/index.html | 6 +- src/index.js | 157 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 159 insertions(+), 4 deletions(-) diff --git a/src/index.html b/src/index.html index 9ea3877..c2c82c6 100644 --- a/src/index.html +++ b/src/index.html @@ -2,7 +2,7 @@ - + 3D Cube Viewer @@ -17,6 +17,10 @@

🖱️ Left click + drag: Rotate around model

🖱️ Right click + drag: Pan

⚙️ Mouse wheel: Zoom in/out

+
+

👆 Single finger drag: Rotate around model

+

🤏 Pinch to zoom: Zoom in/out

+

✌️ Two finger drag: Pan around scene

diff --git a/src/index.js b/src/index.js index ae20576..7636d32 100644 --- a/src/index.js +++ b/src/index.js @@ -17,12 +17,12 @@ function init() { scene = new THREE.Scene(); scene.background = new THREE.Color(0x2c3e50); - // Create camera + // Create camera with extended far clipping plane for better zoom out camera = new THREE.PerspectiveCamera( 75, // Field of view window.innerWidth / window.innerHeight, // Aspect ratio 0.1, // Near clipping plane - 1000 // Far clipping plane + 10000 // Extended far clipping plane for better zoom out ); camera.position.set(20, 20, 20); camera.lookAt(0, 0, 0); @@ -45,7 +45,7 @@ function init() { container.appendChild(renderer.domElement); - // Add orbit controls + // Add orbit controls with enhanced touch support controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; @@ -53,6 +53,27 @@ function init() { controls.enablePan = true; controls.enableRotate = true; + // Touch-specific settings + controls.touches = { + ONE: THREE.TOUCH.ROTATE, // Single finger touch for rotation + TWO: THREE.TOUCH.DOLLY_PAN // Two fingers for zoom and pan + }; + + // Enhanced touch sensitivity and limits + controls.rotateSpeed = 1.0; // Rotation speed + controls.zoomSpeed = 2.0; // Increased zoom speed for faster mouse wheel + controls.panSpeed = 0.8; // Pan speed + // Sync zoom limits with camera clipping planes + controls.minDistance = 0.1; // Match camera near plane + controls.maxDistance = 8000; // Stay within camera far plane (10000) with buffer + + // Smooth touch interactions + controls.enableDamping = true; + controls.dampingFactor = 0.08; // Slightly higher for smoother touch + + // Add custom touch event handlers + setupCustomTouchControls(); + // Add lighting setupLighting(); @@ -66,6 +87,136 @@ function init() { animate(); } +function setupCustomTouchControls() { + const canvas = renderer.domElement; + let touchStartDistance = 0; + let touchStartRotation = { x: 0, y: 0 }; + let lastTouchMoveTime = 0; + + // Variables for touch tracking + let touches = []; + let isRotating = false; + let isZooming = false; + + // Helper function to get touch distance (for pinch zoom) + function getTouchDistance(touch1, touch2) { + const dx = touch1.clientX - touch2.clientX; + const dy = touch1.clientY - touch2.clientY; + return Math.sqrt(dx * dx + dy * dy); + } + + // Helper function to get touch center point + function getTouchCenter(touch1, touch2) { + return { + x: (touch1.clientX + touch2.clientX) / 2, + y: (touch1.clientY + touch2.clientY) / 2 + }; + } + + // Touch start handler + canvas.addEventListener('touchstart', function(event) { + event.preventDefault(); + touches = Array.from(event.touches); + + if (touches.length === 2) { + // Two finger pinch/zoom start + touchStartDistance = getTouchDistance(touches[0], touches[1]); + isZooming = true; + isRotating = false; + } else if (touches.length === 1) { + // Single finger rotation start + touchStartRotation.x = touches[0].clientX; + touchStartRotation.y = touches[0].clientY; + isRotating = true; + isZooming = false; + } + + lastTouchMoveTime = Date.now(); + }, { passive: false }); + + // Touch move handler for enhanced responsiveness + canvas.addEventListener('touchmove', function(event) { + event.preventDefault(); + + const currentTime = Date.now(); + const timeDelta = currentTime - lastTouchMoveTime; + + // Throttle touch move events for performance (max 60fps) + if (timeDelta < 16) return; + + touches = Array.from(event.touches); + + if (touches.length === 2 && isZooming) { + // Handle pinch zoom + const currentDistance = getTouchDistance(touches[0], touches[1]); + const zoomDelta = (currentDistance - touchStartDistance) * 0.01; + + // Apply zoom with smooth scaling + const zoomFactor = Math.exp(-zoomDelta); + const newDistance = controls.object.position.distanceTo(controls.target) * zoomFactor; + + // Clamp zoom within limits + const clampedDistance = Math.max(controls.minDistance, + Math.min(controls.maxDistance, newDistance)); + + // Update camera position + const direction = controls.object.position.clone().sub(controls.target).normalize(); + controls.object.position.copy(controls.target).add(direction.multiplyScalar(clampedDistance)); + + touchStartDistance = currentDistance; + + } else if (touches.length === 1 && isRotating) { + // Enhanced single finger rotation + const rotationSensitivity = 0.005; + const deltaX = (touches[0].clientX - touchStartRotation.x) * rotationSensitivity; + const deltaY = (touches[0].clientY - touchStartRotation.y) * rotationSensitivity; + + // Apply rotation with smooth movement + controls.rotateLeft(-deltaX); + controls.rotateUp(-deltaY); + + touchStartRotation.x = touches[0].clientX; + touchStartRotation.y = touches[0].clientY; + } + + lastTouchMoveTime = currentTime; + controls.update(); + }, { passive: false }); + + // Touch end handler + canvas.addEventListener('touchend', function(event) { + event.preventDefault(); + touches = Array.from(event.touches); + + if (touches.length < 2) { + isZooming = false; + } + if (touches.length < 1) { + isRotating = false; + } + + // Reset if no touches + if (touches.length === 0) { + isZooming = false; + isRotating = false; + } + }, { passive: false }); + + // Prevent context menu on long press + canvas.addEventListener('contextmenu', function(event) { + event.preventDefault(); + }, { passive: false }); + + // Add touch-friendly CSS for better interaction + canvas.style.touchAction = 'none'; + canvas.style.userSelect = 'none'; + canvas.style.webkitUserSelect = 'none'; + canvas.style.mozUserSelect = 'none'; + canvas.style.msUserSelect = 'none'; + + console.log('Custom touch controls initialized'); +} + function setupLighting() { // Ambient light for overall illumination - increased intensity const ambientLight = new THREE.AmbientLight(0x404040, 1.2);