This commit is contained in:
seb
2025-08-25 06:14:34 +02:00
parent 7a4f1fa3df
commit eef1e3a789
2 changed files with 159 additions and 4 deletions

View File

@@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>3D Cube Viewer</title>
</head>
<body>
@@ -17,6 +17,10 @@
<p>🖱️ Left click + drag: Rotate around model</p>
<p>🖱️ Right click + drag: Pan</p>
<p>⚙️ Mouse wheel: Zoom in/out</p>
<hr style="margin: 10px 0; border: 1px solid #555;">
<p>👆 Single finger drag: Rotate around model</p>
<p>🤏 Pinch to zoom: Zoom in/out</p>
<p>✌️ Two finger drag: Pan around scene</p>
</div>
</div>
</body>

View File

@@ -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);