u
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<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>
|
<title>3D Cube Viewer</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -17,6 +17,10 @@
|
|||||||
<p>🖱️ Left click + drag: Rotate around model</p>
|
<p>🖱️ Left click + drag: Rotate around model</p>
|
||||||
<p>🖱️ Right click + drag: Pan</p>
|
<p>🖱️ Right click + drag: Pan</p>
|
||||||
<p>⚙️ Mouse wheel: Zoom in/out</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>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
157
src/index.js
157
src/index.js
@@ -17,12 +17,12 @@ function init() {
|
|||||||
scene = new THREE.Scene();
|
scene = new THREE.Scene();
|
||||||
scene.background = new THREE.Color(0x2c3e50);
|
scene.background = new THREE.Color(0x2c3e50);
|
||||||
|
|
||||||
// Create camera
|
// Create camera with extended far clipping plane for better zoom out
|
||||||
camera = new THREE.PerspectiveCamera(
|
camera = new THREE.PerspectiveCamera(
|
||||||
75, // Field of view
|
75, // Field of view
|
||||||
window.innerWidth / window.innerHeight, // Aspect ratio
|
window.innerWidth / window.innerHeight, // Aspect ratio
|
||||||
0.1, // Near clipping plane
|
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.position.set(20, 20, 20);
|
||||||
camera.lookAt(0, 0, 0);
|
camera.lookAt(0, 0, 0);
|
||||||
@@ -45,7 +45,7 @@ function init() {
|
|||||||
|
|
||||||
container.appendChild(renderer.domElement);
|
container.appendChild(renderer.domElement);
|
||||||
|
|
||||||
// Add orbit controls
|
// Add orbit controls with enhanced touch support
|
||||||
controls = new OrbitControls(camera, renderer.domElement);
|
controls = new OrbitControls(camera, renderer.domElement);
|
||||||
controls.enableDamping = true;
|
controls.enableDamping = true;
|
||||||
controls.dampingFactor = 0.05;
|
controls.dampingFactor = 0.05;
|
||||||
@@ -53,6 +53,27 @@ function init() {
|
|||||||
controls.enablePan = true;
|
controls.enablePan = true;
|
||||||
controls.enableRotate = 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
|
// Add lighting
|
||||||
setupLighting();
|
setupLighting();
|
||||||
|
|
||||||
@@ -66,6 +87,136 @@ function init() {
|
|||||||
animate();
|
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() {
|
function setupLighting() {
|
||||||
// Ambient light for overall illumination - increased intensity
|
// Ambient light for overall illumination - increased intensity
|
||||||
const ambientLight = new THREE.AmbientLight(0x404040, 1.2);
|
const ambientLight = new THREE.AmbientLight(0x404040, 1.2);
|
||||||
|
|||||||
Reference in New Issue
Block a user