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