Freie Kamera eingebaut in Mondphase
This commit is contained in:
@@ -2230,8 +2230,8 @@ body.moonphase-page.has-modal {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: minmax(2.8em, auto) auto;
|
||||
justify-content: flex-start;
|
||||
min-height: 124px;
|
||||
height: 124px;
|
||||
min-height: 165px;
|
||||
height: 190px;
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
@@ -2247,6 +2247,12 @@ body.moonphase-page.has-modal {
|
||||
color: #d8f7ff;
|
||||
}
|
||||
|
||||
.moon-orbit-btn.is-active {
|
||||
background: rgba(169, 255, 143, 0.15);
|
||||
border-color: #6fc85a;
|
||||
color: #c8ffc0;
|
||||
}
|
||||
|
||||
.moon-phase-name {
|
||||
font-family: 'Orbitron', sans-serif;
|
||||
font-size: 1.15rem;
|
||||
|
||||
+61
-6
@@ -162,6 +162,7 @@ try {
|
||||
<div class="moon-phase-name" id="phaseName"></div>
|
||||
<div class="moon-actions">
|
||||
<button type="button" class="date-shift-btn moon-reset-btn" id="resetViewBtn" title="Grafik reset">Grafik reset</button>
|
||||
<button type="button" class="date-shift-btn moon-orbit-btn" id="freeCameraBtn" title="Kamera frei um den Mond bewegen">Freie Kamera</button>
|
||||
<button
|
||||
type="button"
|
||||
class="date-shift-btn moon-action-btn"
|
||||
@@ -334,6 +335,7 @@ const prevDayBtn = document.getElementById('prevDayBtn');
|
||||
const nextDayBtn = document.getElementById('nextDayBtn');
|
||||
const nowBtn = document.getElementById('nowBtn');
|
||||
const resetViewBtn = document.getElementById('resetViewBtn');
|
||||
const freeCameraBtn = document.getElementById('freeCameraBtn');
|
||||
const playPauseBtn = document.getElementById('playPauseBtn');
|
||||
const playbackSpeedGroup = document.getElementById('playbackSpeedGroup');
|
||||
const exportMoonBtn = document.getElementById('exportMoonBtn');
|
||||
@@ -363,6 +365,11 @@ let moonPlaybackActive = false;
|
||||
let moonPlaybackSpeed = 1;
|
||||
let isMoonExportRunning = false;
|
||||
let moonExportRestoreFocus = null;
|
||||
let freeCameraMode = false;
|
||||
let cameraOrbitTheta = 0;
|
||||
let cameraOrbitPhi = Math.PI / 2;
|
||||
let moonDragStartOrbitTheta = 0;
|
||||
let moonDragStartOrbitPhi = Math.PI / 2;
|
||||
const craterLongitudeOffsetDeg = 0.0;
|
||||
const craterLatitudeOffsetDeg = 0.0;
|
||||
const craterOverlayScale = 0.940;
|
||||
@@ -492,9 +499,20 @@ function applyMoonZoom() {
|
||||
return;
|
||||
}
|
||||
|
||||
moonSceneState.camera.position.z = MOON_CAMERA_BASE_Z / getMoonZoomFactor();
|
||||
moonSceneState.camera.position.x = moonPanX;
|
||||
moonSceneState.camera.position.y = moonPanY;
|
||||
const r = MOON_CAMERA_BASE_Z / getMoonZoomFactor();
|
||||
|
||||
if (freeCameraMode) {
|
||||
moonSceneState.camera.position.set(
|
||||
r * Math.sin(cameraOrbitPhi) * Math.sin(cameraOrbitTheta),
|
||||
r * Math.cos(cameraOrbitPhi),
|
||||
r * Math.sin(cameraOrbitPhi) * Math.cos(cameraOrbitTheta)
|
||||
);
|
||||
moonSceneState.camera.lookAt(0, 0, 0);
|
||||
} else {
|
||||
moonSceneState.camera.position.set(moonPanX, moonPanY, r);
|
||||
moonSceneState.camera.lookAt(moonPanX, moonPanY, 0);
|
||||
}
|
||||
|
||||
moonSceneState.camera.updateProjectionMatrix();
|
||||
}
|
||||
|
||||
@@ -506,6 +524,8 @@ function resetMoonView() {
|
||||
moonZoom = 1;
|
||||
moonPanX = 0;
|
||||
moonPanY = 0;
|
||||
cameraOrbitTheta = 0;
|
||||
cameraOrbitPhi = Math.PI / 2;
|
||||
updateMoon();
|
||||
}
|
||||
|
||||
@@ -1130,6 +1150,17 @@ function getMoonDisplayGeometry(width, height, zoom = null) {
|
||||
if (moonSceneState && moonSceneState.camera) {
|
||||
const camera = moonSceneState.camera;
|
||||
const focalLengthPx = (height / 2) / Math.tan(toRadians(camera.fov / 2));
|
||||
|
||||
if (freeCameraMode) {
|
||||
const depth = Math.max(0.001, camera.position.length());
|
||||
const projectedRadius = focalLengthPx * (1.6 / depth) * MOON_PROJECTED_RADIUS_SCALE;
|
||||
return {
|
||||
centerX: width / 2,
|
||||
centerY: height / 2,
|
||||
radius: projectedRadius
|
||||
};
|
||||
}
|
||||
|
||||
const depth = Math.max(0.001, camera.position.z);
|
||||
const projectedRadius = focalLengthPx * (1.6 / depth) * MOON_PROJECTED_RADIUS_SCALE;
|
||||
|
||||
@@ -1463,6 +1494,8 @@ function beginMoonDrag(event) {
|
||||
moonDragStartY = event.clientY;
|
||||
moonDragStartPanX = moonPanX;
|
||||
moonDragStartPanY = moonPanY;
|
||||
moonDragStartOrbitTheta = cameraOrbitTheta;
|
||||
moonDragStartOrbitPhi = cameraOrbitPhi;
|
||||
moonCanvas.classList.add('is-dragging');
|
||||
moonCanvas.setPointerCapture(event.pointerId);
|
||||
}
|
||||
@@ -1474,10 +1507,21 @@ function updateMoonDrag(event) {
|
||||
|
||||
const rect = moonCanvas.getBoundingClientRect();
|
||||
const size = Math.max(1, Math.min(rect.width, rect.height));
|
||||
const panScale = 4.2 / (size * getMoonZoomFactor());
|
||||
|
||||
moonPanX = clampMoonPan(moonDragStartPanX - (event.clientX - moonDragStartX) * panScale);
|
||||
moonPanY = clampMoonPan(moonDragStartPanY + (event.clientY - moonDragStartY) * panScale);
|
||||
if (freeCameraMode) {
|
||||
const sensitivity = 3.0 / size;
|
||||
cameraOrbitTheta = moonDragStartOrbitTheta + (event.clientX - moonDragStartX) * sensitivity;
|
||||
cameraOrbitPhi = THREE.MathUtils.clamp(
|
||||
moonDragStartOrbitPhi - (event.clientY - moonDragStartY) * sensitivity,
|
||||
0.05,
|
||||
Math.PI - 0.05
|
||||
);
|
||||
} else {
|
||||
const panScale = 4.2 / (size * getMoonZoomFactor());
|
||||
moonPanX = clampMoonPan(moonDragStartPanX - (event.clientX - moonDragStartX) * panScale);
|
||||
moonPanY = clampMoonPan(moonDragStartPanY + (event.clientY - moonDragStartY) * panScale);
|
||||
}
|
||||
|
||||
updateMoon();
|
||||
}
|
||||
|
||||
@@ -1527,6 +1571,17 @@ nowBtn.addEventListener('click', () => {
|
||||
updateMoon();
|
||||
});
|
||||
resetViewBtn.addEventListener('click', resetMoonView);
|
||||
freeCameraBtn.addEventListener('click', () => {
|
||||
freeCameraMode = !freeCameraMode;
|
||||
freeCameraBtn.classList.toggle('is-active', freeCameraMode);
|
||||
if (!freeCameraMode) {
|
||||
moonPanX = 0;
|
||||
moonPanY = 0;
|
||||
}
|
||||
cameraOrbitTheta = 0;
|
||||
cameraOrbitPhi = Math.PI / 2;
|
||||
updateMoon();
|
||||
});
|
||||
playPauseBtn.addEventListener('click', toggleMoonPlayback);
|
||||
exportMoonBtn.addEventListener('click', openMoonExportDialog);
|
||||
showAllCratersBtn.addEventListener('click', () => {
|
||||
|
||||
Reference in New Issue
Block a user