release: bump version to 0.44.0
This commit is contained in:
@@ -1668,6 +1668,12 @@ label.is-disabled.earth-mobile-settings-card {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.earth-status-message.gesture {
|
||||
min-width: 0;
|
||||
padding-right: calc(16px * var(--hud-scale));
|
||||
color: #dcecff;
|
||||
}
|
||||
|
||||
.earth-error-message {
|
||||
top: calc(62px * var(--hud-scale));
|
||||
z-index: 211;
|
||||
|
||||
@@ -121,6 +121,19 @@
|
||||
box-shadow: 0 0 4px currentColor;
|
||||
}
|
||||
|
||||
.legend-dot--vessel {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-radius: 0;
|
||||
background: transparent !important;
|
||||
border-left: calc(5px * var(--hud-scale)) solid transparent;
|
||||
border-right: calc(5px * var(--hud-scale)) solid transparent;
|
||||
border-bottom: calc(13px * var(--hud-scale)) solid currentColor;
|
||||
color: inherit;
|
||||
box-shadow: none;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.legend-label {
|
||||
color: var(--hud-text);
|
||||
font-size: calc(0.78rem * var(--hud-scale));
|
||||
|
||||
@@ -9,8 +9,9 @@ export const CONFIG = {
|
||||
earthRadius: 100,
|
||||
rotationSpeed: 0.0005,
|
||||
dragRotationFactorBase: 0.005,
|
||||
dragRotationScaleMin: 0.28,
|
||||
dragRotationScaleMax: 2.0,
|
||||
dragRotationZoomExponent: 1.8,
|
||||
dragRotationScaleMin: 0.12,
|
||||
dragRotationScaleMax: 1.65,
|
||||
};
|
||||
|
||||
export const ROTATION_MODE = {
|
||||
@@ -170,8 +171,8 @@ export const TERRAIN_CONFIG = {
|
||||
|
||||
export const COUNTRY_BOUNDARY_CONFIG = {
|
||||
dataPath: "/earth/data/countries-admin0.min.geojson",
|
||||
lineAltitudeOffset: 0.24,
|
||||
hoverAltitudeOffset: 0.32,
|
||||
lineAltitudeOffset: 0.115,
|
||||
hoverAltitudeOffset: 0.14,
|
||||
lineColor: 0x7fc7ff,
|
||||
lineOpacity: 0.58,
|
||||
lineRenderOrder: 2.2,
|
||||
|
||||
21
frontend/public/earth/js/controls.js
vendored
21
frontend/public/earth/js/controls.js
vendored
@@ -10,7 +10,12 @@ import {
|
||||
ROTATION_MODE,
|
||||
SATELLITE_DISPLAY_STYLES,
|
||||
} from "./constants.js";
|
||||
import { setEarthStatValue, updateZoomDisplay, showStatusMessage } from "./ui.js";
|
||||
import {
|
||||
setEarthStatValue,
|
||||
showGestureStatusMessage,
|
||||
showStatusMessage,
|
||||
updateZoomDisplay,
|
||||
} from "./ui.js";
|
||||
import {
|
||||
toggleTerrain,
|
||||
setDayNightEnabled,
|
||||
@@ -121,6 +126,7 @@ const GRID_LINES_DEFAULT_VERSION = 3;
|
||||
const SATELLITE_DISPLAY_DEFAULT_VERSION = 4;
|
||||
const MEDIA_PANEL_DEFAULT_VERSION = 5;
|
||||
const DEFAULT_EARTH_ZOOM_STEP = 0.01;
|
||||
const ZOOM_STATUS_UPDATE_INTERVAL_MS = 90;
|
||||
let settingsModalTimer = null;
|
||||
let settingsSheetAnimation = null;
|
||||
let terrainToggleToken = 0;
|
||||
@@ -128,6 +134,7 @@ let terrainPrefetchStarted = false;
|
||||
let terrainPrefetchScheduled = false;
|
||||
let focusViewAnimationToken = 0;
|
||||
let earthSettingsDefaults = null;
|
||||
let lastZoomStatusUpdateTime = 0;
|
||||
let earthSettingsState = null;
|
||||
let layerRegistry = new Map();
|
||||
let layerPanelInitialized = false;
|
||||
@@ -1806,6 +1813,15 @@ export function setZoomLevel(nextZoom, camera = activeCamera) {
|
||||
return zoomLevel;
|
||||
}
|
||||
|
||||
export function showZoomStatusCapsule({ force = false } = {}) {
|
||||
const now = Date.now();
|
||||
if (!force && now - lastZoomStatusUpdateTime < ZOOM_STATUS_UPDATE_INTERVAL_MS) {
|
||||
return;
|
||||
}
|
||||
lastZoomStatusUpdateTime = now;
|
||||
showGestureStatusMessage(`缩放 ${Math.round(zoomLevel * 100)}%`, "info");
|
||||
}
|
||||
|
||||
function cancelSettingsSheetAnimation() {
|
||||
if (settingsSheetAnimation) {
|
||||
settingsSheetAnimation.cancel();
|
||||
@@ -2627,6 +2643,7 @@ function setupZoomControls(camera) {
|
||||
|
||||
zoomLevel = newPercent / 100;
|
||||
applyZoom(camera);
|
||||
showZoomStatusCapsule({ force: true });
|
||||
}
|
||||
|
||||
function doContinuousZoom(direction) {
|
||||
@@ -2638,6 +2655,7 @@ function setupZoomControls(camera) {
|
||||
|
||||
zoomLevel = newPercent / 100;
|
||||
applyZoom(camera);
|
||||
showZoomStatusCapsule();
|
||||
}
|
||||
|
||||
function startContinuousZoom(direction) {
|
||||
@@ -2736,6 +2754,7 @@ function setupWheelZoom(camera, renderer) {
|
||||
zoomLevel = Math.max(zoomLevel - 0.1, CONFIG.minZoom);
|
||||
}
|
||||
applyZoom(camera);
|
||||
showZoomStatusCapsule({ force: true });
|
||||
},
|
||||
{ passive: false },
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ const LEGEND_MODES = {
|
||||
satellites: { title: "卫星" },
|
||||
countryBoundaries: { title: "国界" },
|
||||
computeCenters: { title: "算力" },
|
||||
vessels: { title: "船只" },
|
||||
bgp: { title: "BGP" },
|
||||
};
|
||||
|
||||
@@ -15,6 +16,7 @@ let legendItemsByMode = {
|
||||
satellites: [],
|
||||
countryBoundaries: [],
|
||||
computeCenters: [],
|
||||
vessels: [],
|
||||
bgp: [],
|
||||
};
|
||||
|
||||
@@ -81,7 +83,7 @@ function renderLegend(mode) {
|
||||
.map(
|
||||
(item) => `
|
||||
<div class="legend-item">
|
||||
<span class="legend-dot" style="background:${item.color}"></span>
|
||||
<span class="legend-dot legend-dot--${item.shape || "dot"}" style="background:${item.color}; color:${item.color}"></span>
|
||||
<span class="legend-label">${item.label}</span>
|
||||
</div>`,
|
||||
)
|
||||
|
||||
@@ -193,6 +193,7 @@ import {
|
||||
focusEarthView,
|
||||
getZoomLevel,
|
||||
setZoomLevel,
|
||||
showZoomStatusCapsule,
|
||||
teardownControls,
|
||||
getDayNightEnabled,
|
||||
setDayNightEnabledExternal,
|
||||
@@ -366,7 +367,7 @@ function setGlobeDraggingUiState(active) {
|
||||
function getDragRotationFactor() {
|
||||
const zoom = Math.max(getZoomLevel(), 0.01);
|
||||
const scale = THREE.MathUtils.clamp(
|
||||
1 / zoom,
|
||||
Math.pow(zoom, -CONFIG.dragRotationZoomExponent),
|
||||
CONFIG.dragRotationScaleMin,
|
||||
CONFIG.dragRotationScaleMax,
|
||||
);
|
||||
@@ -2365,6 +2366,7 @@ export function init() {
|
||||
setLegendItems("satellites", getSatelliteLegendItems());
|
||||
setLegendItems("countryBoundaries", getCountryBoundaryLegendItems());
|
||||
setLegendItems("computeCenters", getComputeCenterLegendItems());
|
||||
setLegendItems("vessels", getVesselLegendItems());
|
||||
setLegendItems("bgp", getBGPLegendItems());
|
||||
const earthObj = createEarth(scene);
|
||||
applyImmediateView(earthObj, camera);
|
||||
@@ -3358,6 +3360,7 @@ function onPointerDown(event) {
|
||||
pinchGesture = {
|
||||
distance: getTouchDistance(firstPoint, secondPoint),
|
||||
startZoom: getZoomLevel(),
|
||||
statusShown: false,
|
||||
};
|
||||
activeDragPointerId = null;
|
||||
onMouseUp();
|
||||
@@ -3390,6 +3393,8 @@ function onPointerMove(event) {
|
||||
if (pinchGesture.distance > 0) {
|
||||
const scale = nextDistance / pinchGesture.distance;
|
||||
setZoomLevel(pinchGesture.startZoom * scale, camera);
|
||||
showZoomStatusCapsule({ force: !pinchGesture.statusShown });
|
||||
pinchGesture.statusShown = true;
|
||||
suppressNextClick = true;
|
||||
hideTooltip();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ let statusHideTimeoutId = null;
|
||||
const STATUS_BASE_CLASS = "earth-status-message";
|
||||
const STATUS_DISPLAY_MS = 3000;
|
||||
const STATUS_FADE_MS = 280;
|
||||
const GESTURE_STATUS_DISPLAY_MS = 760;
|
||||
let statusQueue = [];
|
||||
let statusBusy = false;
|
||||
let loadingActive = false;
|
||||
@@ -148,6 +149,28 @@ export function queueStatusMessage(message, type = "info") {
|
||||
processStatusQueue();
|
||||
}
|
||||
|
||||
export function showGestureStatusMessage(message, type = "info") {
|
||||
if (loadingActive) return;
|
||||
const statusEl = getElement("status-message");
|
||||
if (!statusEl) return;
|
||||
|
||||
clearStatusTimers();
|
||||
statusBusy = true;
|
||||
buildStatusContent(statusEl, message, type);
|
||||
statusEl.className = `${STATUS_BASE_CLASS} ${type} gesture`;
|
||||
setElementDisplay(statusEl, true, "inline-flex");
|
||||
statusEl.offsetHeight;
|
||||
statusEl.classList.add("visible");
|
||||
|
||||
statusTimeoutId = setTimeout(() => {
|
||||
hideStatusElement(statusEl, () => {
|
||||
statusBusy = false;
|
||||
processStatusQueue();
|
||||
});
|
||||
statusTimeoutId = null;
|
||||
}, GESTURE_STATUS_DISPLAY_MS);
|
||||
}
|
||||
|
||||
// Update coordinates display
|
||||
export function updateCoordinatesDisplay(lat, lon, alt = 0) {
|
||||
const longitudeEl = getElement("longitude-value");
|
||||
|
||||
@@ -246,12 +246,13 @@ export async function showVesselTrack(marker, earth) {
|
||||
|
||||
export function getVesselLegendItems() {
|
||||
return [
|
||||
{ label: "货轮", color: VESSEL_CONFIG.colors.cargo },
|
||||
{ label: "油轮", color: VESSEL_CONFIG.colors.tanker },
|
||||
{ label: "客船", color: VESSEL_CONFIG.colors.passenger },
|
||||
{ label: "渔船", color: VESSEL_CONFIG.colors.fishing },
|
||||
{ label: "军舰", color: VESSEL_CONFIG.colors.military },
|
||||
{ label: "其他", color: VESSEL_CONFIG.colors.other },
|
||||
{ label: "货轮", color: VESSEL_CONFIG.colors.cargo, shape: "vessel" },
|
||||
{ label: "油轮", color: VESSEL_CONFIG.colors.tanker, shape: "vessel" },
|
||||
{ label: "客船", color: VESSEL_CONFIG.colors.passenger, shape: "vessel" },
|
||||
{ label: "渔船", color: VESSEL_CONFIG.colors.fishing, shape: "vessel" },
|
||||
{ label: "军舰", color: VESSEL_CONFIG.colors.military, shape: "vessel" },
|
||||
{ label: "停泊/低速", color: VESSEL_CONFIG.colors.other, shape: "dot" },
|
||||
{ label: "其他船只", color: VESSEL_CONFIG.colors.other, shape: "vessel" },
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user