This commit is contained in:
seb
2025-08-25 06:04:30 +02:00
parent bfcb7af982
commit 16ec4df714

View File

@@ -73,6 +73,8 @@
<p>🖱️ Left click + drag: Rotate around model</p>
<p>🖱️ Right click + drag: Pan</p>
<p>⚙️ Mouse wheel: Zoom in/out</p>
<p>📱 Touch drag: Rotate around model</p>
<p>🤏 Pinch: Zoom in/out</p>
</div>
</div>
@@ -90,6 +92,17 @@
let scene, camera, renderer, controls;
let cube;
// Touch controls variables
let touchState = {
touching: false,
touchCount: 0,
lastTouches: [],
initialDistance: 0,
lastDistance: 0,
rotationStart: { x: 0, y: 0 },
lastRotation: { x: 0, y: 0 }
};
// Initialize the 3D scene
function init() {
// Create container
@@ -135,6 +148,9 @@
controls.enablePan = true;
controls.enableRotate = true;
// Setup touch controls
setupTouchControls(renderer.domElement);
// Add lighting
setupLighting();
@@ -218,6 +234,133 @@
window.environmentMap = texture;
}
function setupTouchControls(domElement) {
// Touch start event
domElement.addEventListener('touchstart', function(event) {
event.preventDefault();
touchState.touching = true;
touchState.touchCount = event.touches.length;
touchState.lastTouches = Array.from(event.touches);
if (event.touches.length === 1) {
// Single touch - prepare for rotation
const touch = event.touches[0];
touchState.rotationStart.x = touch.clientX;
touchState.rotationStart.y = touch.clientY;
touchState.lastRotation.x = touch.clientX;
touchState.lastRotation.y = touch.clientY;
// Disable OrbitControls to prevent conflicts
controls.enabled = false;
} else if (event.touches.length === 2) {
// Two touches - prepare for pinch zoom
const touch1 = event.touches[0];
const touch2 = event.touches[1];
touchState.initialDistance = getTouchDistance(touch1, touch2);
touchState.lastDistance = touchState.initialDistance;
// Disable OrbitControls to prevent conflicts
controls.enabled = false;
}
}, false);
// Touch move event
domElement.addEventListener('touchmove', function(event) {
event.preventDefault();
if (!touchState.touching) return;
if (event.touches.length === 1 && touchState.touchCount === 1) {
// Single touch drag - rotation
const touch = event.touches[0];
const deltaX = touch.clientX - touchState.lastRotation.x;
const deltaY = touch.clientY - touchState.lastRotation.y;
// Apply rotation to the controls
const rotationSpeed = 0.005;
controls.enabled = true; // Temporarily enable to apply rotation
// Simulate mouse movement for OrbitControls
const spherical = new THREE.Spherical();
spherical.setFromVector3(camera.position.clone().sub(controls.target));
spherical.theta -= deltaX * rotationSpeed;
spherical.phi += deltaY * rotationSpeed;
// Constrain phi to prevent camera flipping
spherical.phi = Math.max(0.1, Math.min(Math.PI - 0.1, spherical.phi));
const newPosition = new THREE.Vector3();
newPosition.setFromSpherical(spherical).add(controls.target);
camera.position.copy(newPosition);
camera.lookAt(controls.target);
controls.enabled = false; // Disable again to prevent conflicts
touchState.lastRotation.x = touch.clientX;
touchState.lastRotation.y = touch.clientY;
} else if (event.touches.length === 2) {
// Two touches - pinch zoom
const touch1 = event.touches[0];
const touch2 = event.touches[1];
const currentDistance = getTouchDistance(touch1, touch2);
const scaleFactor = currentDistance / touchState.lastDistance;
// Apply zoom
const zoomSpeed = 0.1;
const direction = camera.position.clone().sub(controls.target).normalize();
const currentDistance3D = camera.position.distanceTo(controls.target);
let newDistance;
if (scaleFactor > 1) {
// Pinching out - zoom in
newDistance = Math.max(1, currentDistance3D * (1 - zoomSpeed * (scaleFactor - 1)));
} else {
// Pinching in - zoom out
newDistance = currentDistance3D * (1 + zoomSpeed * (1 - scaleFactor));
}
camera.position.copy(controls.target.clone().add(direction.multiplyScalar(newDistance)));
touchState.lastDistance = currentDistance;
}
}, false);
// Touch end event
domElement.addEventListener('touchend', function(event) {
event.preventDefault();
touchState.touchCount = event.touches.length;
if (event.touches.length === 0) {
// No more touches - re-enable OrbitControls
touchState.touching = false;
controls.enabled = true;
} else if (event.touches.length === 1 && touchState.touchCount > 1) {
// Switched from multi-touch to single touch
const touch = event.touches[0];
touchState.rotationStart.x = touch.clientX;
touchState.rotationStart.y = touch.clientY;
touchState.lastRotation.x = touch.clientX;
touchState.lastRotation.y = touch.clientY;
}
}, false);
// Prevent context menu on long press
domElement.addEventListener('contextmenu', function(event) {
event.preventDefault();
}, false);
}
function getTouchDistance(touch1, touch2) {
const dx = touch1.clientX - touch2.clientX;
const dy = touch1.clientY - touch2.clientY;
return Math.sqrt(dx * dx + dy * dy);
}
function loadCubeModel() {
// Create loaders
const mtlLoader = new THREE.MTLLoader();