u
This commit is contained in:
@@ -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>
|
||||
|
||||
157
src/index.js
157
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);
|
||||
|
||||
Reference in New Issue
Block a user