u
This commit is contained in:
143
index.html
143
index.html
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user