Update camera configuration and enhance touch controls; implement debounce for camera state logging and add responsive styles for mobile devices.

This commit is contained in:
sebseb7
2025-08-25 07:58:20 +02:00
parent 2ae4fee01a
commit 553d7a5070
3 changed files with 92 additions and 117 deletions

View File

@@ -1,20 +1,20 @@
{
"camera": {
"position": {
"x": 450,
"y": 154,
"z": -130
"x": 514,
"y": 228,
"z": -403
},
"target": {
"x": 50,
"y": 85,
"z": -140
},
"distance": 406,
"distance": 552,
"spherical": {
"radius": 406,
"theta": 1.55,
"phi": 1.4
"radius": 552,
"theta": 2.09,
"phi": 1.31
}
},
"description": "Default camera configuration for 3D model viewer. Position values can be copied from console logs and pasted here to set new defaults."

View File

@@ -120,88 +120,6 @@ async function init() {
function setupCustomTouchControls() {
const canvas = renderer.domElement;
let touchStartDistance = 0;
let lastTouchMoveTime = 0;
// Variables for touch tracking
let touches = [];
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);
}
// Touch start handler - only handle two-finger gestures, let OrbitControls handle single finger
canvas.addEventListener('touchstart', function(event) {
touches = Array.from(event.touches);
if (touches.length === 2) {
// Two finger pinch/zoom start - prevent default for custom handling
event.preventDefault();
touchStartDistance = getTouchDistance(touches[0], touches[1]);
isZooming = true;
} else {
// Single finger - let OrbitControls handle it natively
isZooming = false;
}
lastTouchMoveTime = Date.now();
}, { passive: false });
// Touch move handler - only custom handle pinch zoom
canvas.addEventListener('touchmove', function(event) {
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) {
// Prevent default only for two-finger gestures
event.preventDefault();
// 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;
controls.update();
}
// Single finger rotation handled natively by OrbitControls
lastTouchMoveTime = currentTime;
}, { passive: false });
// Touch end handler
canvas.addEventListener('touchend', function(event) {
touches = Array.from(event.touches);
if (touches.length < 2) {
isZooming = 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';
@@ -210,7 +128,12 @@ function setupCustomTouchControls() {
canvas.style.mozUserSelect = 'none';
canvas.style.msUserSelect = 'none';
console.log('Custom touch controls initialized - OrbitControls handles single finger rotation');
// Prevent context menu on long press
canvas.addEventListener('contextmenu', function(event) {
event.preventDefault();
}, { passive: false });
console.log('Touch controls enabled - OrbitControls handles all touch gestures natively');
}
function setupLighting() {
@@ -544,8 +467,17 @@ function centerModelAndControls(object) {
}
function setupRotationLogging() {
// Log rotation and zoom changes whenever the camera moves
let debounceTimer = null;
// Log rotation and zoom changes with 1-second debounce
controls.addEventListener('change', function() {
// Clear existing timer
if (debounceTimer) {
clearTimeout(debounceTimer);
}
// Set new timer for 1 second delay
debounceTimer = setTimeout(() => {
const distance = camera.position.distanceTo(controls.target);
const position = camera.position.clone();
const target = controls.target.clone();
@@ -572,9 +504,12 @@ function setupRotationLogging() {
console.log(' - Theta (horizontal):', Math.round(spherical.theta * 100) / 100, 'radians');
console.log(' - Phi (vertical):', Math.round(spherical.phi * 100) / 100, 'radians');
console.log('==================');
debounceTimer = null;
}, 1000);
});
console.log('Rotation logging enabled - camera state will be logged on every change');
console.log('Rotation logging enabled - camera state will be logged 1 second after movement stops');
}
function animate() {

View File

@@ -23,6 +23,46 @@ body {
border-radius: 10px;
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
max-width: 300px;
}
/* Mobile and tablet responsive styles - covers both portrait and landscape */
@media (max-width: 1024px) {
#info {
top: 5px;
left: 5px;
padding: 4px 6px;
font-size: 10px;
max-width: 140px;
border-radius: 4px;
}
#info h2 {
font-size: 11px;
margin: 0 0 3px 0;
}
#info p {
margin: 1px 0;
line-height: 1.1;
}
#info hr {
margin: 3px 0 !important;
border: 0.5px solid #555;
}
}
/* Very small screens (phones in portrait) */
@media (max-width: 480px) {
#info {
max-width: 120px;
font-size: 9px;
}
#info h2 {
font-size: 10px;
}
}
#loading {