release: bump version to 0.67.0
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / delivery (push) Has been cancelled
release / images (push) Has been cancelled

This commit is contained in:
rayd1o
2026-05-27 13:50:16 +08:00
parent d15a9d488a
commit b18ffa0b0a
46 changed files with 2116 additions and 648 deletions

View File

@@ -2822,6 +2822,7 @@ label.is-disabled.earth-mobile-settings-card {
display: flex;
align-items: center;
gap: 12px;
min-width: 0;
}
.earth-settings-segmented {
@@ -2908,10 +2909,17 @@ label.is-disabled.earth-mobile-settings-card {
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 0 calc(30px * var(--hud-scale));
width: calc(30px * var(--hud-scale));
height: calc(30px * var(--hud-scale));
min-width: calc(30px * var(--hud-scale));
min-height: calc(30px * var(--hud-scale));
max-width: calc(30px * var(--hud-scale));
max-height: calc(30px * var(--hud-scale));
aspect-ratio: 1 / 1;
padding: 0;
border: 1px solid rgba(122, 180, 255, 0.24);
border-radius: 999px;
border-radius: 50%;
background:
radial-gradient(circle at 35% 22%, rgba(255, 255, 255, 0.2), transparent 58%),
linear-gradient(180deg, rgba(121, 159, 207, 0.18), rgba(72, 101, 139, 0.24));
@@ -2926,12 +2934,16 @@ label.is-disabled.earth-mobile-settings-card {
}
.earth-settings-reload-action--text {
flex-basis: auto;
width: auto;
max-width: none;
min-width: calc(46px * var(--hud-scale));
padding: 0 calc(12px * var(--hud-scale));
aspect-ratio: auto;
font: inherit;
font-size: calc(0.7rem * var(--hud-scale));
font-weight: 600;
border-radius: 999px;
}
.earth-settings-reload-action[hidden] {
@@ -3076,6 +3088,7 @@ label.is-disabled.earth-mobile-settings-card {
.earth-settings-slider {
flex: 1 1 auto;
min-width: calc(120px * var(--hud-scale));
width: 100%;
height: calc(4px * var(--hud-scale));
appearance: none;

View File

@@ -214,7 +214,6 @@ const computeCenterIconLayer = createInteractableLayer({
},
icon: {
coordinates: "canvas",
colorable: false,
fitSize: COMPUTE_CENTER_ICON_FIT_SIZE,
glowBlur: 16,
getSource({ marker, item }) {

View File

@@ -64,6 +64,8 @@ export const SURFACE_HOVER_INFO_MODES = {
export const DEFAULT_SURFACE_HOVER_INFO_MODE =
SURFACE_HOVER_INFO_MODES.FULL;
export const EARTH_SURFACE_TEXTURE_ALTITUDE_OFFSET = 0.48;
export const CRUISE_CONFIG = {
dwellMs: 7_000,
focusDurationMs: 1_400,
@@ -233,8 +235,12 @@ export const COUNTRY_BOUNDARY_CONFIG = {
tilePrefetchRing: 1,
tileDebounceMs: 180,
tileCacheLimit: 150,
lineAltitudeOffset: 0.115,
hoverAltitudeOffset: 0.115,
// Keep boundary/coastline strokes on the same shell as the high-res earth
// texture overlay. A lower or higher radius creates visible parallax while
// the globe rotates.
lineAltitudeOffset: EARTH_SURFACE_TEXTURE_ALTITUDE_OFFSET,
hoverAltitudeOffset: EARTH_SURFACE_TEXTURE_ALTITUDE_OFFSET,
claimLineAltitudeOffset: 0,
hoverMissStickyMs: 160,
lineColor: 0x7fc7ff,
lineOpacity: 0.58,
@@ -540,7 +546,7 @@ export const EARTH_MATERIAL_CONFIG = {
shininess: 12,
emissive: 0x010609,
opacity: 1,
textureOverlayAltitudeOffset: 0.48,
textureOverlayAltitudeOffset: EARTH_SURFACE_TEXTURE_ALTITUDE_OFFSET,
textureOverlayOpacity: 0.88,
textureOverlayRenderOrder: 0.96,
textureOverlaySpecular: 0x05080d,

View File

@@ -185,6 +185,11 @@ const KEYBOARD_ROTATION_STOP_SPEED = 0.012;
const KEYBOARD_ZOOM_STEP = 0.1;
const WHEEL_ZOOM_STEP = 0.1;
const WHEEL_ZOOM_DURATION_MS = 180;
const WHEEL_TRACKPAD_PIXEL_THRESHOLD = 48;
const WHEEL_TRACKPAD_DEADZONE = 0.35;
const WHEEL_TRACKPAD_RESIDUAL_WINDOW_MS = 140;
const WHEEL_TRACKPAD_RESIDUAL_RATIO = 0.65;
const WHEEL_TRACKPAD_SENSITIVITY = 0.0024;
const TARGET_SWITCH_ZOOM_IN_PHASE = 0.28;
const TARGET_SWITCH_ROTATE_PHASE = 0.5;
let settingsModalTimer = null;
@@ -655,7 +660,7 @@ function stopKeyboardRotationControl({ actionId = null, restoreAutoRotate = fals
}
function applyKeyboardZoom(direction) {
setZoomLevel(zoomLevel + direction * KEYBOARD_ZOOM_STEP, activeCamera);
setZoomLevel(getZoomLevelFromCamera(activeCamera) + direction * KEYBOARD_ZOOM_STEP, activeCamera);
showZoomStatusCapsule({ force: true });
}
@@ -1318,6 +1323,19 @@ function clampEarthZoomLevel(nextZoom) {
return Math.min(CONFIG.maxZoom, Math.max(CONFIG.minZoom, parsedZoom));
}
function getZoomLevelFromCamera(camera = activeCamera) {
const cameraZ = Number(camera?.position?.z);
if (!Number.isFinite(cameraZ) || cameraZ <= 0) {
return clampEarthZoomLevel(zoomLevel);
}
return clampEarthZoomLevel(CONFIG.defaultCameraZ / cameraZ);
}
function syncZoomLevelFromCamera(camera = activeCamera) {
zoomLevel = getZoomLevelFromCamera(camera);
return zoomLevel;
}
function formatZoomPercent(zoom) {
return `${Math.round(zoom * 100)}%`;
}
@@ -2188,8 +2206,7 @@ function setDefaultEarthZoom(nextZoom, { persist = true, applyToCurrentView = tr
syncDefaultEarthZoomUi(defaultEarthZoom);
if (applyToCurrentView && activeCamera) {
zoomLevel = defaultEarthZoom;
applyZoom(activeCamera);
setZoomLevel(defaultEarthZoom, activeCamera);
}
if (persist) {
@@ -3110,12 +3127,7 @@ export function applyImmediateView(targetEarthObj, camera, options = {}) {
targetEarthObj.rotation.x = nextRotation.x;
targetEarthObj.rotation.y = nextRotation.y;
targetEarthObj.rotation.z = nextRotation.z;
zoomLevel = zoom;
if (camera) {
camera.position.z = CONFIG.defaultCameraZ / zoomLevel;
updateZoomDisplay(zoomLevel, camera.position.z.toFixed(0));
}
setZoomLevel(zoom, camera);
}
export function setZoomLevel(nextZoom, camera = activeCamera) {
@@ -3127,13 +3139,16 @@ export function setZoomLevel(nextZoom, camera = activeCamera) {
return zoomLevel;
}
export function showZoomStatusCapsule({ force = false } = {}) {
export function showZoomStatusCapsule({ force = false, zoom = null } = {}) {
const now = Date.now();
if (!force && now - lastZoomStatusUpdateTime < ZOOM_STATUS_UPDATE_INTERVAL_MS) {
return;
}
lastZoomStatusUpdateTime = now;
showGestureStatusMessage(`缩放 ${Math.round(zoomLevel * 100)}%`, "info");
const currentZoom = Number.isFinite(Number(zoom))
? clampEarthZoomLevel(zoom)
: syncZoomLevelFromCamera(activeCamera);
showGestureStatusMessage(`缩放 ${Math.round(currentZoom * 100)}%`, "info");
}
function cancelSettingsSheetAnimation() {
@@ -4692,27 +4707,25 @@ function setupZoomControls(camera) {
const MAX_PERCENT = CONFIG.maxZoom * 100;
function doZoomStep(direction) {
let currentPercent = Math.round(zoomLevel * 100);
let currentPercent = Math.round(getZoomLevelFromCamera(camera) * 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;
zoomLevel = newPercent / 100;
applyZoom(camera);
setZoomLevel(newPercent / 100, camera);
showZoomStatusCapsule({ force: true });
}
function doContinuousZoom(direction) {
let currentPercent = Math.round(zoomLevel * 100);
let currentPercent = Math.round(getZoomLevelFromCamera(camera) * 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);
setZoomLevel(newPercent / 100, camera);
showZoomStatusCapsule();
}
@@ -4775,10 +4788,8 @@ function setupZoomControls(camera) {
bindListener(zoomOut, "touchend", () => handleMouseUp(-1));
bindListener(zoomValue, "click", () => {
const startZoomVal = zoomLevel;
const startZoomVal = getZoomLevelFromCamera(camera);
const targetZoom = getDefaultEarthZoomLevel();
const startDistance = CONFIG.defaultCameraZ / startZoomVal;
const targetDistance = CONFIG.defaultCameraZ / targetZoom;
animateValue(
0,
@@ -4786,14 +4797,11 @@ function setupZoomControls(camera) {
600,
(progress) => {
const ease = 1 - Math.pow(1 - progress, 3);
zoomLevel = startZoomVal + (targetZoom - startZoomVal) * ease;
camera.position.z = CONFIG.defaultCameraZ / zoomLevel;
const distance =
startDistance + (targetDistance - startDistance) * ease;
updateZoomDisplay(zoomLevel, distance.toFixed(0));
const nextZoom = startZoomVal + (targetZoom - startZoomVal) * ease;
setZoomLevel(nextZoom, camera);
},
() => {
zoomLevel = targetZoom;
setZoomLevel(targetZoom, camera);
showStatusMessage(getZoomResetStatusMessage(targetZoom), "info");
},
);
@@ -4802,9 +4810,51 @@ function setupZoomControls(camera) {
function setupWheelZoom(camera, renderer) {
let wheelZoomFrameId = null;
let wheelZoomTarget = zoomLevel;
let wheelZoomStart = zoomLevel;
let wheelZoomTarget = getZoomLevelFromCamera(camera);
let wheelZoomStart = wheelZoomTarget;
let wheelZoomStartAt = 0;
let lastTrackpadDirection = 0;
let suppressedTrackpadDirection = 0;
let suppressedTrackpadUntil = 0;
let suppressedTrackpadMagnitude = 0;
function getWheelPixelDelta(event) {
if (event.deltaMode === WheelEvent.DOM_DELTA_LINE) {
return event.deltaY * 16;
}
if (event.deltaMode === WheelEvent.DOM_DELTA_PAGE) {
return event.deltaY * window.innerHeight;
}
return event.deltaY;
}
function isTrackpadWheel(event, pixelDelta) {
return event.deltaMode === WheelEvent.DOM_DELTA_PIXEL &&
Math.abs(pixelDelta) < WHEEL_TRACKPAD_PIXEL_THRESHOLD;
}
function shouldSuppressTrackpadResidual(pixelDelta) {
const direction = Math.sign(pixelDelta);
const magnitude = Math.abs(pixelDelta);
const now = performance.now();
return direction !== 0 &&
direction === suppressedTrackpadDirection &&
now < suppressedTrackpadUntil &&
magnitude < suppressedTrackpadMagnitude * WHEEL_TRACKPAD_RESIDUAL_RATIO;
}
function recordTrackpadWheel(pixelDelta) {
const direction = Math.sign(pixelDelta);
const magnitude = Math.abs(pixelDelta);
if (direction === 0) return;
const now = performance.now();
if (lastTrackpadDirection !== 0 && direction !== lastTrackpadDirection) {
suppressedTrackpadDirection = lastTrackpadDirection;
suppressedTrackpadUntil = now + WHEEL_TRACKPAD_RESIDUAL_WINDOW_MS;
suppressedTrackpadMagnitude = magnitude;
}
lastTrackpadDirection = direction;
}
function stopWheelZoomAnimation() {
if (wheelZoomFrameId !== null) {
@@ -4824,28 +4874,55 @@ function setupWheelZoom(camera, renderer) {
1,
);
const ease = 1 - Math.pow(1 - progress, 3);
zoomLevel = wheelZoomStart + (wheelZoomTarget - wheelZoomStart) * ease;
applyZoom(camera);
setZoomLevel(
wheelZoomStart + (wheelZoomTarget - wheelZoomStart) * ease,
camera,
);
if (progress < 1) {
wheelZoomFrameId = window.requestAnimationFrame(animateWheelZoom);
return;
}
zoomLevel = wheelZoomTarget;
applyZoom(camera);
setZoomLevel(wheelZoomTarget, camera);
wheelZoomFrameId = null;
wheelZoomStartAt = 0;
}
function startWheelZoomAnimation() {
wheelZoomStart = zoomLevel;
wheelZoomStart = getZoomLevelFromCamera(camera);
wheelZoomStartAt = 0;
if (wheelZoomFrameId === null) {
wheelZoomFrameId = window.requestAnimationFrame(animateWheelZoom);
}
}
function applyMouseWheelZoom(direction) {
suppressedTrackpadDirection = 0;
suppressedTrackpadUntil = 0;
const baseZoom = wheelZoomFrameId === null
? getZoomLevelFromCamera(camera)
: wheelZoomTarget;
wheelZoomTarget = clampEarthZoomLevel(
baseZoom + direction * WHEEL_ZOOM_STEP,
);
stopWheelZoomAnimation();
startWheelZoomAnimation();
showZoomStatusCapsule({ force: true, zoom: wheelZoomTarget });
}
function applyTrackpadWheelZoom(pixelDelta) {
if (Math.abs(pixelDelta) < WHEEL_TRACKPAD_DEADZONE) return;
if (shouldSuppressTrackpadResidual(pixelDelta)) return;
stopWheelZoomAnimation();
const currentZoom = getZoomLevelFromCamera(camera);
const nextZoom = currentZoom * Math.exp(-pixelDelta * WHEEL_TRACKPAD_SENSITIVITY);
wheelZoomTarget = setZoomLevel(nextZoom, camera);
wheelZoomStart = wheelZoomTarget;
recordTrackpadWheel(pixelDelta);
showZoomStatusCapsule({ force: true, zoom: wheelZoomTarget });
}
cleanupFns.push(stopWheelZoomAnimation);
bindListener(
@@ -4853,25 +4930,17 @@ function setupWheelZoom(camera, renderer) {
"wheel",
(e) => {
e.preventDefault();
const direction = e.deltaY < 0 ? 1 : -1;
const baseZoom =
wheelZoomFrameId === null ? zoomLevel : wheelZoomTarget;
wheelZoomTarget = clampEarthZoomLevel(
baseZoom + direction * WHEEL_ZOOM_STEP,
);
startWheelZoomAnimation();
showZoomStatusCapsule({ force: true });
const pixelDelta = getWheelPixelDelta(e);
if (isTrackpadWheel(e, pixelDelta)) {
applyTrackpadWheelZoom(pixelDelta);
return;
}
applyMouseWheelZoom(pixelDelta < 0 ? 1 : -1);
},
{ passive: false },
);
}
function applyZoom(camera) {
camera.position.z = CONFIG.defaultCameraZ / zoomLevel;
const distance = camera.position.z.toFixed(0);
updateZoomDisplay(zoomLevel, distance);
}
function animateValue(start, end, duration, onUpdate, onComplete) {
const animationToken = ++focusViewAnimationToken;
const startTime = performance.now();
@@ -5800,7 +5869,7 @@ export function focusEarthView(camera, options = {}) {
const startRotX = earthObj.rotation.x;
const startRotY = earthObj.rotation.y;
const startRotZ = earthObj.rotation.z;
const startZoom = zoomLevel;
const startZoom = getZoomLevelFromCamera(camera);
const defaultZoom = getDefaultEarthZoomLevel();
const shouldRestoreZoomViaDefault =
zoomTransitionMode === "restore-current-via-default" &&
@@ -5829,30 +5898,26 @@ export function focusEarthView(camera, options = {}) {
if (progress < rotateStartProgress) {
const zoomProgress = progress / rotateStartProgress;
const zoomEase = 1 - Math.pow(1 - zoomProgress, 3);
zoomLevel = startZoom + (defaultZoom - startZoom) * zoomEase;
setZoomLevel(startZoom + (defaultZoom - startZoom) * zoomEase, camera);
} else if (progress <= rotateEndProgress) {
zoomLevel = defaultZoom;
setZoomLevel(defaultZoom, camera);
} else {
const zoomProgress = (progress - rotateEndProgress) / (1 - rotateEndProgress);
const zoomEase = 1 - Math.pow(1 - zoomProgress, 3);
zoomLevel = defaultZoom + (startZoom - defaultZoom) * zoomEase;
setZoomLevel(defaultZoom + (startZoom - defaultZoom) * zoomEase, camera);
}
} else {
earthObj.rotation.x = startRotX + (nextRotation.x - startRotX) * ease;
earthObj.rotation.y = startRotY + (nextRotation.y - startRotY) * ease;
earthObj.rotation.z = startRotZ + (nextRotation.z - startRotZ) * ease;
zoomLevel = startZoom + (zoom - startZoom) * ease;
setZoomLevel(startZoom + (zoom - startZoom) * ease, camera);
}
camera.position.z = CONFIG.defaultCameraZ / zoomLevel;
updateZoomDisplay(zoomLevel, camera.position.z.toFixed(0));
},
() => {
zoomLevel = shouldRestoreZoomViaDefault ? startZoom : zoom;
setZoomLevel(shouldRestoreZoomViaDefault ? startZoom : zoom, camera);
earthObj.rotation.x = nextRotation.x;
earthObj.rotation.y = nextRotation.y;
earthObj.rotation.z = nextRotation.z;
camera.position.z = CONFIG.defaultCameraZ / zoomLevel;
updateZoomDisplay(zoomLevel, camera.position.z.toFixed(0));
if (!suppressStatus) {
showStatusMessage("视角已重置", "info");
}
@@ -5863,7 +5928,7 @@ export function focusEarthView(camera, options = {}) {
}
export function getZoomLevel() {
return zoomLevel;
return syncZoomLevelFromCamera(activeCamera);
}
export function getDefaultEarthZoomLevel() {

View File

@@ -210,7 +210,7 @@ function boundaryLineRadius({ claim = false } = {}) {
return (
CONFIG.earthRadius +
COUNTRY_BOUNDARY_CONFIG.lineAltitudeOffset +
(claim ? 0.018 : 0)
(claim ? COUNTRY_BOUNDARY_CONFIG.claimLineAltitudeOffset : 0)
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,6 @@ import {
showStatusMessage,
queueStatusMessage,
updateCoordinatesDisplay,
updateZoomDisplay,
updateEarthStats,
setEarthStatValue,
setLoading,
@@ -301,6 +300,8 @@ export let scene;
export let camera;
export let renderer;
const WEBGL_GPU_DIAGNOSTICS_EVENT = "earth:gpu-diagnostics";
let isDragging = false;
let previousMousePosition = { x: 0, y: 0 };
let targetRotation = { x: 0, y: 0 };
@@ -451,6 +452,29 @@ function getViewportAspect() {
return window.innerWidth / window.innerHeight;
}
function getWebGLGpuDiagnostics(activeRenderer) {
const gl = activeRenderer?.getContext?.();
if (!gl) return null;
const debugInfo = gl.getExtension?.("WEBGL_debug_renderer_info");
const attrs = gl.getContextAttributes?.() || {};
return {
requestedPowerPreference: "high-performance",
contextPowerPreference: attrs.powerPreference || null,
vendor: debugInfo ? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) : gl.getParameter(gl.VENDOR),
renderer: debugInfo ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) : gl.getParameter(gl.RENDERER),
antialias: Boolean(attrs.antialias),
alpha: Boolean(attrs.alpha),
};
}
function publishWebGLGpuDiagnostics(activeRenderer) {
const diagnostics = getWebGLGpuDiagnostics(activeRenderer);
if (!diagnostics) return;
window.__planetEarthGpu = diagnostics;
console.info("[智能星球] WebGL GPU diagnostics", diagnostics);
window.dispatchEvent(new CustomEvent(WEBGL_GPU_DIAGNOSTICS_EVENT, { detail: diagnostics }));
}
function syncRendererViewport() {
if (!camera || !renderer) return;
camera.aspect = getViewportAspect();
@@ -793,12 +817,30 @@ function isSameVessel(marker1, marker2) {
return Boolean(marker1 && marker2 && marker1.userData?.mmsi === marker2.userData?.mmsi);
}
function getFirstObjectIntersection(intersections) {
return intersections.find((hit) => !hit?.cluster && hit?.object)?.object || null;
}
function getPrimaryClusterHit(...intersectionGroups) {
return intersectionGroups
.flat()
.filter((hit) => hit?.cluster && Number(hit.clusterCount) > 1)
.sort((a, b) => a.distancePxSq - b.distancePxSq)[0] || null;
}
function getClusterBriefHtml(hit) {
const count = Number(hit?.clusterCount || hit?.clusterMarkers?.length || 0);
return `<strong>共 ${count} 个对象</strong><br><span>放大后可查看单个图标</span>`;
}
function getPrimaryBGPHoverTarget(bgpAnomalyIntersects, bgpCollectorIntersects) {
if (bgpAnomalyIntersects.length > 0) {
return bgpAnomalyIntersects[0].object;
const anomalyMarker = getFirstObjectIntersection(bgpAnomalyIntersects);
if (anomalyMarker) {
return anomalyMarker;
}
if (bgpCollectorIntersects.length > 0) {
return bgpCollectorIntersects[0].object;
const collectorMarker = getFirstObjectIntersection(bgpCollectorIntersects);
if (collectorMarker) {
return collectorMarker;
}
return null;
}
@@ -808,8 +850,8 @@ function getPrimaryBGPClickTarget(
bgpAnomalyIntersects,
bgpCollectorIntersects,
) {
const anomalyMarker = bgpAnomalyIntersects[0]?.object || null;
const collectorMarker = bgpCollectorIntersects[0]?.object || null;
const anomalyMarker = getFirstObjectIntersection(bgpAnomalyIntersects);
const collectorMarker = getFirstObjectIntersection(bgpCollectorIntersects);
if (!anomalyMarker && !collectorMarker) return null;
if (!anomalyMarker) return collectorMarker;
if (!collectorMarker) return anomalyMarker;
@@ -952,19 +994,23 @@ function getMotionIconCandidates() {
const candidates = [];
if (getShowBGP()) {
getBGPEventIconPointerIntersections(sharedOptions).forEach((hit) => {
if (hit.cluster || !hit.object) return;
candidates.push({ type: "bgp", object: hit.object, screen: getMotionScreenPointFromWorld(hit.point), distancePxSq: hit.distancePxSq });
});
getBGPCollectorIconPointerIntersections(sharedOptions).forEach((hit) => {
if (hit.cluster || !hit.object) return;
candidates.push({ type: "bgp_collector", object: hit.object, screen: getMotionScreenPointFromWorld(hit.point), distancePxSq: hit.distancePxSq });
});
}
if (getShowComputeCenters()) {
getComputeCenterIconPointerIntersections(sharedOptions).forEach((hit) => {
if (hit.cluster || !hit.object) return;
candidates.push({ type: "compute_center", object: hit.object, screen: getMotionScreenPointFromWorld(hit.point), distancePxSq: hit.distancePxSq });
});
}
if (getShowVessels()) {
getVesselIconPointerIntersections(sharedOptions).forEach((hit) => {
if (hit.cluster || !hit.object) return;
candidates.push({ type: "vessel", object: hit.object, screen: getMotionScreenPointFromWorld(hit.point), distancePxSq: hit.distancePxSq });
});
}
@@ -3961,7 +4007,7 @@ export function init() {
0.1,
5000,
);
camera.position.z = CONFIG.defaultCameraZ;
setZoomLevel(getDefaultEarthZoomLevel(), camera);
setSatelliteCamera(camera);
renderer = new THREE.WebGLRenderer({
@@ -3972,6 +4018,7 @@ export function init() {
syncRendererViewport();
renderer.setClearColor(0x02040a, 1);
renderer.setPixelRatio(window.devicePixelRatio);
publishWebGLGpuDiagnostics(renderer);
const container = document.getElementById("container");
if (container) {
@@ -5287,13 +5334,17 @@ function onMouseMove(event) {
bgpAnomalyIntersects,
bgpCollectorIntersects,
);
const hoveredClusterHit = getPrimaryClusterHit(
bgpAnomalyIntersects,
bgpCollectorIntersects,
computeCenterIntersects,
);
if (hoveredBGP && !isSameBGPMarker(hoveredBGP, hoveredBGPMarker)) {
clearTransientHoverState();
}
const hoveredComputeCenterMarker =
computeCenterIntersects.length > 0 ? computeCenterIntersects[0].object : null;
const hoveredComputeCenterMarker = getFirstObjectIntersection(computeCenterIntersects);
const hoveredVesselMarker =
vesselPick.checked && vesselIntersects.length > 0 ? vesselIntersects[0].object : null;
const earthPoint = screenToEarthCoords(
@@ -5357,6 +5408,20 @@ function onMouseMove(event) {
let objectTooltipShown = false;
if (
hoveredClusterHit &&
!hoveredBGPMarker &&
!hoveredComputeCenterMarker &&
lockedObjectType !== "bgp" &&
lockedObjectType !== "bgp_collector" &&
lockedObjectType !== "compute_center"
) {
showTooltip(
event.clientX + TOOLTIP_CURSOR_OFFSET,
event.clientY + TOOLTIP_CURSOR_OFFSET,
getClusterBriefHtml(hoveredClusterHit),
);
objectTooltipShown = true;
} else if (
hoveredBGPMarker &&
getShowBGP() &&
lockedObjectType !== "bgp" &&
@@ -5663,9 +5728,7 @@ function onClick(event) {
const clickedBGPMarker = getShowBGP()
? getPrimaryBGPClickTarget(event, bgpAnomalyIntersects, bgpCollectorIntersects)
: null;
const clickedComputeCenterMarker = computeCenterIntersects.length > 0
? computeCenterIntersects[0].object
: null;
const clickedComputeCenterMarker = getFirstObjectIntersection(computeCenterIntersects);
const clickedVesselMarker = vesselIntersects.length > 0
? vesselIntersects[0].object
: null;