release: bump version to 0.43.0
This commit is contained in:
@@ -168,6 +168,19 @@ import {
|
||||
toggleComputeCenters,
|
||||
updateComputeCenterVisualState,
|
||||
} from "./compute-centers.js";
|
||||
import {
|
||||
clearVesselData,
|
||||
clearVesselSelection,
|
||||
getShowVessels,
|
||||
getVesselCount,
|
||||
getVesselLegendItems,
|
||||
getVesselMarkers,
|
||||
loadVessels,
|
||||
setVesselMarkerState,
|
||||
showVesselTrack,
|
||||
toggleVessels,
|
||||
updateVesselVisualState,
|
||||
} from "./vessels.js";
|
||||
import {
|
||||
setupControls,
|
||||
getAutoRotate,
|
||||
@@ -228,6 +241,7 @@ let inertialVelocity = { x: 0, y: 0 };
|
||||
let hoveredCable = null;
|
||||
let hoveredBGP = null;
|
||||
let hoveredComputeCenter = null;
|
||||
let hoveredVessel = null;
|
||||
let hoveredSatellite = null;
|
||||
let hoveredSatelliteIndex = null;
|
||||
let lockedSatellite = null;
|
||||
@@ -251,6 +265,7 @@ let isDataLoading = false;
|
||||
let currentLoadToken = 0;
|
||||
let cablesEnabled = true;
|
||||
let satellitesEnabled = false;
|
||||
let vesselsEnabled = false;
|
||||
let cableToggleToken = 0;
|
||||
let satelliteToggleToken = 0;
|
||||
let satelliteHydrationToken = 0;
|
||||
@@ -278,6 +293,8 @@ const scratchBGPDirection = new THREE.Vector3();
|
||||
const scratchBGPWorldPosition = new THREE.Vector3();
|
||||
const scratchComputeCenterDirection = new THREE.Vector3();
|
||||
const scratchComputeCenterWorldPosition = new THREE.Vector3();
|
||||
const scratchVesselDirection = new THREE.Vector3();
|
||||
const scratchVesselWorldPosition = new THREE.Vector3();
|
||||
const scratchSatelliteWorldPosition = new THREE.Vector3();
|
||||
const scratchSatelliteScreenPosition = new THREE.Vector3();
|
||||
const scratchViewCenterWorld = new THREE.Vector3();
|
||||
@@ -425,6 +442,7 @@ export function clearLockedObject() {
|
||||
clearCableSelection();
|
||||
clearBGPSelection();
|
||||
clearComputeCenterSelection();
|
||||
clearVesselSelection();
|
||||
clearRelatedSatelliteHighlights();
|
||||
setSatelliteRingState(null, "none", null);
|
||||
clearRuntimeSelection();
|
||||
@@ -498,9 +516,11 @@ function resetTransientComputeCenterStates() {
|
||||
function clearTransientHoverState() {
|
||||
resetTransientBGPStates();
|
||||
resetTransientComputeCenterStates();
|
||||
resetTransientVesselStates();
|
||||
clearCountryBoundaryHover();
|
||||
hoveredBGP = null;
|
||||
hoveredComputeCenter = null;
|
||||
hoveredVessel = null;
|
||||
|
||||
if (hoveredCable && !isSameCable(hoveredCable, lockedObject)) {
|
||||
setCableState(hoveredCable.userData.cableId, CABLE_STATE.NORMAL);
|
||||
@@ -515,6 +535,25 @@ function clearTransientHoverState() {
|
||||
setHoveredSatelliteIndex(null);
|
||||
}
|
||||
|
||||
function getFrontFacingVesselMarkers(markers) {
|
||||
const earth = getEarth();
|
||||
if (!earth) return markers;
|
||||
|
||||
scratchCameraToEarth.subVectors(camera.position, earth.position).normalize();
|
||||
|
||||
return markers.filter((marker) => {
|
||||
scratchVesselWorldPosition.copy(marker.position);
|
||||
marker.parent?.localToWorld(scratchVesselWorldPosition);
|
||||
scratchVesselDirection
|
||||
.subVectors(scratchVesselWorldPosition, earth.position)
|
||||
.normalize();
|
||||
return (
|
||||
scratchCameraToEarth.dot(scratchVesselDirection) >
|
||||
SATELLITE_CONFIG.frontFacingDotThreshold
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function applyBGPHoverState(marker) {
|
||||
resetTransientBGPStates();
|
||||
if (!marker) {
|
||||
@@ -549,6 +588,30 @@ function applyComputeCenterHoverState(marker) {
|
||||
}
|
||||
}
|
||||
|
||||
function resetTransientVesselStates() {
|
||||
getVesselMarkers().forEach((marker) => {
|
||||
if (marker !== lockedObject) {
|
||||
setVesselMarkerState(marker, "normal");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function applyVesselHoverState(marker) {
|
||||
resetTransientVesselStates();
|
||||
if (!marker) {
|
||||
hoveredVessel = null;
|
||||
return;
|
||||
}
|
||||
hoveredVessel = marker;
|
||||
if (marker !== lockedObject) {
|
||||
setVesselMarkerState(marker, "hover");
|
||||
}
|
||||
}
|
||||
|
||||
function isSameVessel(marker1, marker2) {
|
||||
return Boolean(marker1 && marker2 && marker1.userData?.mmsi === marker2.userData?.mmsi);
|
||||
}
|
||||
|
||||
function getPrimaryBGPHoverTarget(bgpAnomalyIntersects, bgpCollectorIntersects) {
|
||||
if (bgpAnomalyIntersects.length > 0) {
|
||||
return bgpAnomalyIntersects[0].object;
|
||||
@@ -665,6 +728,37 @@ function showComputeCenterInfo(marker, coords) {
|
||||
}, coords);
|
||||
}
|
||||
|
||||
function formatVesselStatus(navStatus) {
|
||||
if (navStatus === 1) return "锚泊";
|
||||
if (navStatus === 5) return "停靠";
|
||||
if (navStatus === 0) return "航行中";
|
||||
return navStatus ?? "-";
|
||||
}
|
||||
|
||||
function showVesselInfo(marker, coords) {
|
||||
setLegendMode("vessels");
|
||||
showInfoCard("vessel", {
|
||||
name: marker.userData?.name || `MMSI ${marker.userData?.mmsi}`,
|
||||
mmsi: marker.userData?.mmsi,
|
||||
imo: marker.userData?.imo || "-",
|
||||
flag: marker.userData?.flag || "-",
|
||||
vessel_type: marker.userData?.vessel_type_name || "-",
|
||||
speed: marker.userData?.sog ?? "-",
|
||||
course: marker.userData?.cog ?? marker.userData?.heading ?? "-",
|
||||
status: formatVesselStatus(marker.userData?.nav_status),
|
||||
length: marker.userData?.length ?? "-",
|
||||
received_at: marker.userData?.received_at
|
||||
? new Date(marker.userData.received_at).toLocaleString("zh-CN", { hour12: false })
|
||||
: "-",
|
||||
}, coords);
|
||||
}
|
||||
|
||||
function getVesselBriefHtml(marker) {
|
||||
const name = marker.userData?.name || `MMSI ${marker.userData?.mmsi}`;
|
||||
const speed = marker.userData?.sog ?? "-";
|
||||
return `<strong>${name}</strong><br>${marker.userData?.vessel_type_name || "Vessel"} · ${speed} kn`;
|
||||
}
|
||||
|
||||
function getComputeCenterBriefHtml(marker) {
|
||||
const name = marker.userData?.name || "算力中心";
|
||||
const type = formatComputeCenterTypeLabel(marker.userData?.site_type);
|
||||
@@ -864,6 +958,13 @@ function getComputeCenterFocusCoords(marker) {
|
||||
return { lat, lon };
|
||||
}
|
||||
|
||||
function getVesselFocusCoords(marker) {
|
||||
const lat = marker?.userData?.latitude;
|
||||
const lon = marker?.userData?.longitude;
|
||||
if (typeof lat !== "number" || typeof lon !== "number") return null;
|
||||
return { lat, lon };
|
||||
}
|
||||
|
||||
async function focusSearchTarget(coords, zoom = Math.max(getZoomLevel(), 1.12)) {
|
||||
if (!coords || !camera) return;
|
||||
await focusEarthView(camera, {
|
||||
@@ -1037,6 +1138,33 @@ async function focusSearchComputeCenter(marker) {
|
||||
);
|
||||
}
|
||||
|
||||
async function focusSearchVessel(marker) {
|
||||
await setVesselsEnabled(true, {
|
||||
suppressStatus: true,
|
||||
suppressLoadingUi: true,
|
||||
});
|
||||
interruptCruisePresentation({ resetLoop: true });
|
||||
clearLockedObject();
|
||||
setAutoRotate(false);
|
||||
|
||||
const coords = getVesselFocusCoords(marker);
|
||||
if (coords) {
|
||||
await focusSearchTarget(coords, Math.max(getZoomLevel(), 1.2));
|
||||
}
|
||||
|
||||
setVesselMarkerState(marker, "locked");
|
||||
lockedObject = marker;
|
||||
lockedObjectType = "vessel";
|
||||
showVesselInfo(marker, getSearchCardCoords());
|
||||
showVesselTrack(marker, getEarth()).catch((error) => {
|
||||
console.warn("船只轨迹加载失败:", error);
|
||||
});
|
||||
showStatusMessage(
|
||||
`已定位船只:${marker.userData?.name || marker.userData?.mmsi || "未知船只"}`,
|
||||
"info",
|
||||
);
|
||||
}
|
||||
|
||||
function resolveEarthSearchResults(query) {
|
||||
const results = [];
|
||||
const normalizedQuery = query.trim().toLowerCase();
|
||||
@@ -1205,6 +1333,33 @@ function resolveEarthSearchResults(query) {
|
||||
});
|
||||
});
|
||||
|
||||
getVesselMarkers().forEach((marker) => {
|
||||
const score = computeSearchScore(
|
||||
normalizedQuery,
|
||||
marker.userData?.name,
|
||||
marker.userData?.mmsi,
|
||||
marker.userData?.imo,
|
||||
marker.userData?.flag,
|
||||
marker.userData?.vessel_type_name,
|
||||
"船只 船舶 ais vessel ship maritime",
|
||||
);
|
||||
if (score < 0) return;
|
||||
results.push({
|
||||
id: `vessel:${marker.userData?.mmsi || marker.uuid}`,
|
||||
kind: "vessel",
|
||||
icon: "directions_boat",
|
||||
typeLabel: "船只",
|
||||
title: marker.userData?.name || `MMSI ${marker.userData?.mmsi}`,
|
||||
subtitle: [
|
||||
marker.userData?.vessel_type_name,
|
||||
marker.userData?.flag,
|
||||
marker.userData?.sog !== undefined ? `${marker.userData.sog} kn` : null,
|
||||
].filter(Boolean).join(" · ") || "AIS 船只",
|
||||
score,
|
||||
entity: marker,
|
||||
});
|
||||
});
|
||||
|
||||
return results
|
||||
.sort((left, right) => {
|
||||
if (right.score !== left.score) return right.score - left.score;
|
||||
@@ -1234,6 +1389,10 @@ async function handleSearchSelection(result) {
|
||||
}
|
||||
if (result.kind === "compute_center") {
|
||||
await focusSearchComputeCenter(result.entity);
|
||||
return;
|
||||
}
|
||||
if (result.kind === "vessel") {
|
||||
await focusSearchVessel(result.entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1270,6 +1429,7 @@ function applyEarthStatsSummary(summary) {
|
||||
landingPointCount: `${summary.landingPointCount}个`,
|
||||
satelliteCount: `${summary.satelliteCount} 颗`,
|
||||
computeCenterCount: `${summary.computeCenterCount} 个`,
|
||||
vesselCount: `${summary.vesselCount} 艘`,
|
||||
bgpAnomalyCount: `${summary.bgpEventCount} 起`,
|
||||
bgpCollectorCount: `${summary.bgpCollectorCount} 个`,
|
||||
bgpStatusSummary: formatBGPStatusFromSummary(summary),
|
||||
@@ -1291,6 +1451,7 @@ async function loadEarthStatsSummary() {
|
||||
landingPointCount: toCount(stats.landing_point_count),
|
||||
satelliteCount: toCount(stats.satellite_count),
|
||||
computeCenterCount: toCount(stats.compute_center_count),
|
||||
vesselCount: toCount(stats.vessel_count),
|
||||
bgpEventCount: toCount(stats.bgp_event_count),
|
||||
bgpIncidentCount: toCount(stats.bgp_incident_count),
|
||||
bgpAnomalyCount: toCount(stats.bgp_anomaly_count),
|
||||
@@ -1945,6 +2106,23 @@ function updateSatelliteToggleUi(enabled, satelliteCount = getSatelliteCount())
|
||||
setEarthStatValue("satellite-count", `${resolvedCount} 颗`);
|
||||
}
|
||||
|
||||
function updateVesselHud(result = {}) {
|
||||
const count = Number(result.totalCount ?? getVesselCount() ?? 0);
|
||||
setEarthStatValue("vessel-count", `${count} 艘`);
|
||||
}
|
||||
|
||||
function updateVesselToggleUi(enabled, vesselCount = getVesselCount()) {
|
||||
const vesselBtn = document.getElementById("toggle-vessels");
|
||||
if (vesselBtn) {
|
||||
setLayerButtonState(vesselBtn, {
|
||||
active: enabled,
|
||||
loading: false,
|
||||
tooltip: enabled ? "隐藏船只" : "显示船只",
|
||||
});
|
||||
}
|
||||
setEarthStatValue("vessel-count", `${vesselCount || 0} 艘`);
|
||||
}
|
||||
|
||||
function updateCableToggleUi(enabled) {
|
||||
const cableBtn = document.getElementById("toggle-cables");
|
||||
if (cableBtn) {
|
||||
@@ -2063,6 +2241,29 @@ async function ensureSatellitesEnabled() {
|
||||
return loadResult.count;
|
||||
}
|
||||
|
||||
async function ensureVesselsEnabled() {
|
||||
if (!scene || !camera || !renderer || destroyed) return 0;
|
||||
const earth = getEarth();
|
||||
if (!earth) return 0;
|
||||
|
||||
vesselsEnabled = true;
|
||||
const result = await loadVessels(scene, earth);
|
||||
toggleVessels(true);
|
||||
updateVesselToggleUi(true, result.totalCount);
|
||||
setLegendItems("vessels", getVesselLegendItems());
|
||||
refreshLegend();
|
||||
return result.totalCount;
|
||||
}
|
||||
|
||||
function disableVessels() {
|
||||
vesselsEnabled = false;
|
||||
toggleVessels(false);
|
||||
clearVesselSelection();
|
||||
updateVesselToggleUi(false, 0);
|
||||
setLegendItems("vessels", getVesselLegendItems());
|
||||
refreshLegend();
|
||||
}
|
||||
|
||||
function disableSatellites() {
|
||||
satellitesEnabled = false;
|
||||
satelliteToggleToken += 1;
|
||||
@@ -2079,6 +2280,7 @@ function updateStatsSummary() {
|
||||
const landingPointCount =
|
||||
getLandingPoints().length || earthStatsSummary?.landingPointCount || 0;
|
||||
const satelliteCount = getSatelliteCount() || earthStatsSummary?.satelliteCount || 0;
|
||||
const vesselCount = getVesselCount() || earthStatsSummary?.vesselCount || 0;
|
||||
const computeCenterCount =
|
||||
getComputeCenterCount() || earthStatsSummary?.computeCenterCount || 0;
|
||||
const bgpEventCount = getBGPCount() || earthStatsSummary?.bgpEventCount || 0;
|
||||
@@ -2088,6 +2290,7 @@ function updateStatsSummary() {
|
||||
cableCount: `${cableCount}个`,
|
||||
landingPointCount: `${landingPointCount}个`,
|
||||
satelliteCount: `${satelliteCount} 颗`,
|
||||
vesselCount: `${vesselCount} 艘`,
|
||||
computeCenterCount: `${computeCenterCount} 个`,
|
||||
bgpAnomalyCount: `${bgpEventCount} 起`,
|
||||
bgpCollectorCount: `${bgpCollectorCount} 个`,
|
||||
@@ -2333,6 +2536,7 @@ async function loadData() {
|
||||
clearBGPData(earth);
|
||||
clearCableData(earth);
|
||||
clearComputeCenterData(earth);
|
||||
clearVesselData(earth);
|
||||
clearSatelliteData();
|
||||
clearCountryBoundaryHover();
|
||||
|
||||
@@ -2370,8 +2574,10 @@ async function loadData() {
|
||||
updateCableToggleUi,
|
||||
updateSatelliteToggleUi,
|
||||
updateComputeCenterHud,
|
||||
updateVesselHud,
|
||||
updateBGPHud,
|
||||
getShowComputeCenters,
|
||||
getShowVessels,
|
||||
getShowCountryBoundaries,
|
||||
getShowBGP,
|
||||
isEarthTextureVisible: () => getEarthTextureVisible(),
|
||||
@@ -2429,6 +2635,7 @@ async function loadData() {
|
||||
setLegendItems("satellites", getSatelliteLegendItems());
|
||||
setLegendItems("countryBoundaries", getCountryBoundaryLegendItems());
|
||||
setLegendItems("computeCenters", getComputeCenterLegendItems());
|
||||
setLegendItems("vessels", getVesselLegendItems());
|
||||
setLegendItems("bgp", getBGPLegendItems());
|
||||
refreshLegend();
|
||||
setLoading(false);
|
||||
@@ -2463,6 +2670,10 @@ export function getSatellitesEnabled() {
|
||||
return satellitesEnabled;
|
||||
}
|
||||
|
||||
export function getVesselsEnabled() {
|
||||
return vesselsEnabled;
|
||||
}
|
||||
|
||||
export async function setCablesEnabled(
|
||||
enabled,
|
||||
{ suppressStatus = false, suppressLoadingUi = false } = {},
|
||||
@@ -2668,6 +2879,62 @@ export async function setSatellitesEnabled(
|
||||
}
|
||||
}
|
||||
|
||||
export async function setVesselsEnabled(
|
||||
enabled,
|
||||
{ suppressStatus = false, suppressLoadingUi = false } = {},
|
||||
) {
|
||||
if (enabled === vesselsEnabled) {
|
||||
updateVesselToggleUi(enabled);
|
||||
return getVesselCount();
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
clearSelectionAndInfo();
|
||||
disableVessels();
|
||||
if (!suppressStatus) {
|
||||
showStatusMessage("船只已隐藏", "info");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!suppressLoadingUi) {
|
||||
setLoadingMessage("正在加载船只数据...");
|
||||
setLoading(true);
|
||||
hideError();
|
||||
}
|
||||
|
||||
try {
|
||||
const vesselCount = await ensureVesselsEnabled();
|
||||
if (!suppressStatus) {
|
||||
showStatusMessage("船只已显示", "info");
|
||||
}
|
||||
return vesselCount;
|
||||
} catch (error) {
|
||||
vesselsEnabled = false;
|
||||
clearVesselData(getEarth());
|
||||
updateVesselToggleUi(false, 0);
|
||||
const message = `船只加载失败: ${error?.message || String(error)}`;
|
||||
void reportEarthClientLog({
|
||||
level: "error",
|
||||
category: "layer-toggle",
|
||||
module: "vessels",
|
||||
message,
|
||||
detail: error,
|
||||
});
|
||||
if (!suppressLoadingUi) {
|
||||
showError(message);
|
||||
}
|
||||
if (!suppressStatus) {
|
||||
showStatusMessage(message, "error");
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
if (!suppressLoadingUi) {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
const handleResize = () => onWindowResize();
|
||||
const handleVisibilityChange = () => onVisibilityChange();
|
||||
@@ -2865,6 +3132,11 @@ function onMouseMove(event) {
|
||||
const computeCenterIntersects = getShowComputeCenters()
|
||||
? interactionRaycaster.intersectObjects(frontFacingComputeCenterMarkers)
|
||||
: [];
|
||||
const vesselIntersects = getShowVessels()
|
||||
? interactionRaycaster.intersectObjects(
|
||||
getFrontFacingVesselMarkers(getVesselMarkers()),
|
||||
)
|
||||
: [];
|
||||
|
||||
let hoveredSat = null;
|
||||
let hoveredSatIndexFromIntersect = null;
|
||||
@@ -2886,6 +3158,8 @@ function onMouseMove(event) {
|
||||
|
||||
const hoveredComputeCenterMarker =
|
||||
computeCenterIntersects.length > 0 ? computeCenterIntersects[0].object : null;
|
||||
const hoveredVesselMarker =
|
||||
vesselIntersects.length > 0 ? vesselIntersects[0].object : null;
|
||||
|
||||
if (
|
||||
hoveredComputeCenter &&
|
||||
@@ -2893,6 +3167,9 @@ function onMouseMove(event) {
|
||||
) {
|
||||
clearTransientHoverState();
|
||||
}
|
||||
if (hoveredVessel && !isSameVessel(hoveredVessel, hoveredVesselMarker)) {
|
||||
clearTransientHoverState();
|
||||
}
|
||||
|
||||
if (
|
||||
hoveredCable &&
|
||||
@@ -2936,6 +3213,18 @@ function onMouseMove(event) {
|
||||
getComputeCenterBriefHtml(hoveredComputeCenterMarker),
|
||||
);
|
||||
objectTooltipShown = true;
|
||||
} else if (
|
||||
hoveredVesselMarker &&
|
||||
getShowVessels() &&
|
||||
lockedObjectType !== "vessel"
|
||||
) {
|
||||
applyVesselHoverState(hoveredVesselMarker);
|
||||
showTooltip(
|
||||
event.clientX + TOOLTIP_CURSOR_OFFSET,
|
||||
event.clientY + TOOLTIP_CURSOR_OFFSET,
|
||||
getVesselBriefHtml(hoveredVesselMarker),
|
||||
);
|
||||
objectTooltipShown = true;
|
||||
} else if (cableIntersects.length > 0 && getShowCables()) {
|
||||
const cable = cableIntersects[0].object;
|
||||
hoveredCable = cable;
|
||||
@@ -2966,9 +3255,12 @@ function onMouseMove(event) {
|
||||
applyBGPHoverState(lockedObject);
|
||||
} else if (lockedObjectType === "compute_center" && lockedObject) {
|
||||
applyComputeCenterHoverState(lockedObject);
|
||||
} else if (lockedObjectType === "vessel" && lockedObject) {
|
||||
applyVesselHoverState(lockedObject);
|
||||
} else if (!lockedObjectType && !isCruisePresentationPinned()) {
|
||||
resetTransientBGPStates();
|
||||
resetTransientComputeCenterStates();
|
||||
resetTransientVesselStates();
|
||||
hideInfoCard();
|
||||
}
|
||||
|
||||
@@ -3185,6 +3477,11 @@ function onClick(event) {
|
||||
getFrontFacingComputeCenterMarkers(getComputeCenterMarkers()),
|
||||
)
|
||||
: [];
|
||||
const vesselIntersects = getShowVessels()
|
||||
? interactionRaycaster.intersectObjects(
|
||||
getFrontFacingVesselMarkers(getVesselMarkers()),
|
||||
)
|
||||
: [];
|
||||
const satIntersects = getSatellitePointerIntersections(event);
|
||||
|
||||
const clickedBGPMarker = getShowBGP()
|
||||
@@ -3193,6 +3490,9 @@ function onClick(event) {
|
||||
const clickedComputeCenterMarker = computeCenterIntersects.length > 0
|
||||
? computeCenterIntersects[0].object
|
||||
: null;
|
||||
const clickedVesselMarker = vesselIntersects.length > 0
|
||||
? vesselIntersects[0].object
|
||||
: null;
|
||||
|
||||
if (clickedBGPMarker?.userData?.type === "bgp") {
|
||||
interruptCruisePresentation();
|
||||
@@ -3260,6 +3560,26 @@ function onClick(event) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clickedVesselMarker?.userData?.type === "vessel") {
|
||||
interruptCruisePresentation();
|
||||
clearLockedObject();
|
||||
|
||||
const clickedMarker = clickedVesselMarker;
|
||||
setVesselMarkerState(clickedMarker, "locked");
|
||||
lockedObject = clickedMarker;
|
||||
lockedObjectType = "vessel";
|
||||
setAutoRotate(false);
|
||||
showVesselInfo(clickedMarker, { x: event.clientX, y: event.clientY });
|
||||
showVesselTrack(clickedMarker, earth).catch((error) => {
|
||||
console.warn("船只轨迹加载失败:", error);
|
||||
});
|
||||
showStatusMessage(
|
||||
`已选择船只: ${clickedMarker.userData?.name || clickedMarker.userData?.mmsi}`,
|
||||
"info",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cableIntersects.length > 0 && getShowCables()) {
|
||||
interruptCruisePresentation();
|
||||
clearLockedObject();
|
||||
@@ -3412,6 +3732,7 @@ function animate() {
|
||||
: null;
|
||||
updateBGPVisualState(lockedObjectType, lockedObject, camera, activeCruiseMarker);
|
||||
updateComputeCenterVisualState(lockedObjectType, lockedObject, camera);
|
||||
updateVesselVisualState(lockedObjectType, lockedObject, camera);
|
||||
|
||||
if (lockedObjectType === "cable" && lockedObject) {
|
||||
applyLandingPointVisualState(lockedObject.userData.name, false, camera);
|
||||
|
||||
Reference in New Issue
Block a user