|
|
|
|
@@ -5,6 +5,7 @@ import { updateZoomDisplay, showStatusMessage } from './ui.js';
|
|
|
|
|
import { toggleTerrain } from './earth.js';
|
|
|
|
|
import { reloadData } from './main.js';
|
|
|
|
|
import { toggleSatellites, toggleTrails, getShowSatellites, getSatelliteCount } from './satellites.js';
|
|
|
|
|
import { toggleCables, getShowCables } from './cables.js';
|
|
|
|
|
|
|
|
|
|
export let autoRotate = true;
|
|
|
|
|
export let zoomLevel = 1.0;
|
|
|
|
|
@@ -23,33 +24,18 @@ export function setupControls(camera, renderer, scene, earth) {
|
|
|
|
|
|
|
|
|
|
function setupZoomControls(camera) {
|
|
|
|
|
let zoomInterval = null;
|
|
|
|
|
let lastDirection = 0;
|
|
|
|
|
let isSnapped = false;
|
|
|
|
|
let holdTimeout = null;
|
|
|
|
|
let startTime = 0;
|
|
|
|
|
const HOLD_THRESHOLD = 150;
|
|
|
|
|
const LONG_PRESS_TICK = 50;
|
|
|
|
|
const CLICK_STEP = 10;
|
|
|
|
|
|
|
|
|
|
const MIN_PERCENT = CONFIG.minZoom * 100;
|
|
|
|
|
const MAX_PERCENT = CONFIG.maxZoom * 100;
|
|
|
|
|
|
|
|
|
|
function adjustZoom(direction) {
|
|
|
|
|
const currentPercent = Math.round(zoomLevel * 100);
|
|
|
|
|
let newPercent;
|
|
|
|
|
|
|
|
|
|
if (direction > 0) {
|
|
|
|
|
if (!isSnapped || currentPercent % 10 !== 0) {
|
|
|
|
|
newPercent = Math.ceil(currentPercent / 10) * 10;
|
|
|
|
|
if (newPercent <= currentPercent) newPercent = currentPercent + 10;
|
|
|
|
|
isSnapped = true;
|
|
|
|
|
} else {
|
|
|
|
|
newPercent = currentPercent + 10;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (!isSnapped || currentPercent % 10 !== 0) {
|
|
|
|
|
newPercent = Math.floor(currentPercent / 10) * 10;
|
|
|
|
|
if (newPercent >= currentPercent) newPercent = currentPercent - 10;
|
|
|
|
|
isSnapped = true;
|
|
|
|
|
} else {
|
|
|
|
|
newPercent = currentPercent - 10;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
function doZoomStep(direction) {
|
|
|
|
|
let currentPercent = Math.round(zoomLevel * 100);
|
|
|
|
|
let newPercent = direction > 0 ? currentPercent + CLICK_STEP : currentPercent - CLICK_STEP;
|
|
|
|
|
|
|
|
|
|
if (newPercent > MAX_PERCENT) newPercent = MAX_PERCENT;
|
|
|
|
|
if (newPercent < MIN_PERCENT) newPercent = MIN_PERCENT;
|
|
|
|
|
@@ -58,13 +44,22 @@ function setupZoomControls(camera) {
|
|
|
|
|
applyZoom(camera);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function startZoom(direction) {
|
|
|
|
|
isSnapped = false;
|
|
|
|
|
lastDirection = direction;
|
|
|
|
|
adjustZoom(direction);
|
|
|
|
|
function doContinuousZoom(direction) {
|
|
|
|
|
let currentPercent = Math.round(zoomLevel * 100);
|
|
|
|
|
let newPercent = direction > 0 ? currentPercent + 1 : currentPercent - 1;
|
|
|
|
|
|
|
|
|
|
if (newPercent > MAX_PERCENT) newPercent = MAX_PERCENT;
|
|
|
|
|
if (newPercent < MIN_PERCENT) newPercent = MIN_PERCENT;
|
|
|
|
|
|
|
|
|
|
zoomLevel = newPercent / 100;
|
|
|
|
|
applyZoom(camera);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function startContinuousZoom(direction) {
|
|
|
|
|
doContinuousZoom(direction);
|
|
|
|
|
zoomInterval = setInterval(() => {
|
|
|
|
|
adjustZoom(direction);
|
|
|
|
|
}, 150);
|
|
|
|
|
doContinuousZoom(direction);
|
|
|
|
|
}, LONG_PRESS_TICK);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function stopZoom() {
|
|
|
|
|
@@ -72,29 +67,49 @@ function setupZoomControls(camera) {
|
|
|
|
|
clearInterval(zoomInterval);
|
|
|
|
|
zoomInterval = null;
|
|
|
|
|
}
|
|
|
|
|
if (holdTimeout) {
|
|
|
|
|
clearTimeout(holdTimeout);
|
|
|
|
|
holdTimeout = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
document.getElementById('zoom-in').addEventListener('mousedown', () => startZoom(1));
|
|
|
|
|
document.getElementById('zoom-in').addEventListener('mouseup', stopZoom);
|
|
|
|
|
document.getElementById('zoom-in').addEventListener('mouseleave', stopZoom);
|
|
|
|
|
document.getElementById('zoom-in').addEventListener('touchstart', (e) => { e.preventDefault(); startZoom(1); });
|
|
|
|
|
document.getElementById('zoom-in').addEventListener('touchend', stopZoom);
|
|
|
|
|
function handleMouseDown(direction) {
|
|
|
|
|
startTime = Date.now();
|
|
|
|
|
stopZoom();
|
|
|
|
|
holdTimeout = setTimeout(() => {
|
|
|
|
|
startContinuousZoom(direction);
|
|
|
|
|
}, HOLD_THRESHOLD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
document.getElementById('zoom-out').addEventListener('mousedown', () => startZoom(-1));
|
|
|
|
|
document.getElementById('zoom-out').addEventListener('mouseup', stopZoom);
|
|
|
|
|
function handleMouseUp(direction) {
|
|
|
|
|
const heldTime = Date.now() - startTime;
|
|
|
|
|
stopZoom();
|
|
|
|
|
if (heldTime < HOLD_THRESHOLD) {
|
|
|
|
|
doZoomStep(direction);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
document.getElementById('zoom-in').addEventListener('mousedown', () => handleMouseDown(1));
|
|
|
|
|
document.getElementById('zoom-in').addEventListener('mouseup', () => handleMouseUp(1));
|
|
|
|
|
document.getElementById('zoom-in').addEventListener('mouseleave', stopZoom);
|
|
|
|
|
document.getElementById('zoom-in').addEventListener('touchstart', (e) => { e.preventDefault(); handleMouseDown(1); });
|
|
|
|
|
document.getElementById('zoom-in').addEventListener('touchend', () => handleMouseUp(1));
|
|
|
|
|
|
|
|
|
|
document.getElementById('zoom-out').addEventListener('mousedown', () => handleMouseDown(-1));
|
|
|
|
|
document.getElementById('zoom-out').addEventListener('mouseup', () => handleMouseUp(-1));
|
|
|
|
|
document.getElementById('zoom-out').addEventListener('mouseleave', stopZoom);
|
|
|
|
|
document.getElementById('zoom-out').addEventListener('touchstart', (e) => { e.preventDefault(); startZoom(-1); });
|
|
|
|
|
document.getElementById('zoom-out').addEventListener('touchend', stopZoom);
|
|
|
|
|
document.getElementById('zoom-out').addEventListener('touchstart', (e) => { e.preventDefault(); handleMouseDown(-1); });
|
|
|
|
|
document.getElementById('zoom-out').addEventListener('touchend', () => handleMouseUp(-1));
|
|
|
|
|
|
|
|
|
|
document.getElementById('zoom-value').addEventListener('click', function() {
|
|
|
|
|
const startZoom = zoomLevel;
|
|
|
|
|
const startZoomVal = zoomLevel;
|
|
|
|
|
const targetZoom = 1.0;
|
|
|
|
|
const startDistance = CONFIG.defaultCameraZ / startZoom;
|
|
|
|
|
const startDistance = CONFIG.defaultCameraZ / startZoomVal;
|
|
|
|
|
const targetDistance = CONFIG.defaultCameraZ / targetZoom;
|
|
|
|
|
|
|
|
|
|
animateValue(0, 1, 600, (progress) => {
|
|
|
|
|
const ease = 1 - Math.pow(1 - progress, 3);
|
|
|
|
|
zoomLevel = startZoom + (targetZoom - startZoom) * ease;
|
|
|
|
|
zoomLevel = startZoomVal + (targetZoom - startZoomVal) * ease;
|
|
|
|
|
camera.position.z = CONFIG.defaultCameraZ / zoomLevel;
|
|
|
|
|
const distance = startDistance + (targetDistance - startDistance) * ease;
|
|
|
|
|
updateZoomDisplay(zoomLevel, distance.toFixed(0));
|
|
|
|
|
@@ -103,12 +118,6 @@ function setupZoomControls(camera) {
|
|
|
|
|
showStatusMessage('缩放已重置到100%', 'info');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const slider = document.getElementById('zoom-slider');
|
|
|
|
|
slider?.addEventListener('input', (e) => {
|
|
|
|
|
zoomLevel = parseFloat(e.target.value);
|
|
|
|
|
applyZoom(camera);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setupWheelZoom(camera, renderer) {
|
|
|
|
|
@@ -235,6 +244,14 @@ function setupTerrainControls() {
|
|
|
|
|
showStatusMessage(showTrails ? '轨迹已显示' : '轨迹已隐藏', 'info');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
document.getElementById('toggle-cables').addEventListener('click', function() {
|
|
|
|
|
const showCables = !getShowCables();
|
|
|
|
|
toggleCables(showCables);
|
|
|
|
|
this.classList.toggle('active', showCables);
|
|
|
|
|
this.querySelector('.tooltip').textContent = showCables ? '隐藏线缆' : '显示线缆';
|
|
|
|
|
showStatusMessage(showCables ? '线缆已显示' : '线缆已隐藏', 'info');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
document.getElementById('reload-data').addEventListener('click', async () => {
|
|
|
|
|
await reloadData();
|
|
|
|
|
showStatusMessage('数据已重新加载', 'success');
|
|
|
|
|
|