fix(earth): highlight all cable segments by cable_id

- Add cable_id mapping to group MultiLineString segments
- Highlight all segments of same cable on hover
- Highlight all segments of same cable on click lock
- Reset all segments when clearing lock
- Add pulse animation to all locked cable segments
- Fix hover/click behavior with cable_id grouping
This commit is contained in:
rayd1o
2026-03-12 12:51:07 +08:00
parent aaae6a53c3
commit ceb1b728d5
2 changed files with 81 additions and 23 deletions

View File

@@ -14,7 +14,7 @@ import {
hideTooltip
} from './ui.js';
import { createEarth, createClouds, createTerrain, createStars, createGridLines, toggleTerrain, getEarth } from './earth.js';
import { loadGeoJSONFromPath, loadLandingPoints, handleCableClick, clearCableSelection, getCableLines } from './cables.js';
import { loadGeoJSONFromPath, loadLandingPoints, handleCableClick, clearCableSelection, getCableLines, getCablesById } from './cables.js';
import { setupControls, getAutoRotate, getShowTerrain, zoomLevel, setAutoRotate, toggleAutoRotate } from './controls.js';
export let scene, camera, renderer;
@@ -23,6 +23,7 @@ let isDragging = false;
let previousMousePosition = { x: 0, y: 0 };
let hoveredCable = null;
let lockedCable = null;
let lockedCableData = null;
window.addEventListener('error', (e) => {
console.error('全局错误:', e.error);
@@ -149,17 +150,27 @@ function onMouseMove(event, camera) {
const intersects = raycaster.intersectObjects(frontCables);
if (hoveredCable && hoveredCable !== lockedCable) {
if (hoveredCable.userData.originalColor !== undefined) {
hoveredCable.material.color.setHex(hoveredCable.userData.originalColor);
}
const prevCableId = hoveredCable.userData.cableId;
const prevSameCables = getCablesById(prevCableId);
prevSameCables.forEach(c => {
if (c.userData.originalColor !== undefined) {
c.material.color.setHex(c.userData.originalColor);
}
});
hoveredCable = null;
}
if (intersects.length > 0) {
const cable = intersects[0].object;
const cableId = cable.userData.cableId;
const sameCables = getCablesById(cableId);
if (cable !== lockedCable) {
cable.material.color.setHex(0xffffff);
cable.material.opacity = 1;
sameCables.forEach(c => {
c.material.color.setHex(0xffffff);
c.material.opacity = 1;
});
hoveredCable = cable;
hoveredCable = cable;
}
@@ -174,7 +185,15 @@ function onMouseMove(event, camera) {
hideTooltip();
} else {
if (!lockedCable) {
if (lockedCable && lockedCableData) {
document.getElementById('cable-name').textContent =
lockedCableData.name || lockedCableData.shortname || '未命名电缆';
document.getElementById('cable-owner').textContent = lockedCableData.owner || '-';
document.getElementById('cable-status').textContent = lockedCableData.status || '-';
document.getElementById('cable-length').textContent = lockedCableData.length || '-';
document.getElementById('cable-coords').textContent = '-';
document.getElementById('cable-rfs').textContent = lockedCableData.rfs || '-';
} else {
document.getElementById('cable-name').textContent = '点击电缆查看详情';
document.getElementById('cable-owner').textContent = '-';
document.getElementById('cable-status').textContent = '-';
@@ -236,23 +255,41 @@ function onClick(event, camera, renderer) {
const intersects = raycaster.intersectObjects(frontCables);
if (intersects.length > 0) {
if (lockedCable && lockedCable !== intersects[0].object) {
if (lockedCable.userData.originalColor !== undefined) {
lockedCable.material.color.setHex(lockedCable.userData.originalColor);
}
if (lockedCable) {
const prevCableId = lockedCable.userData.cableId;
const prevSameCables = getCablesById(prevCableId);
prevSameCables.forEach(c => {
if (c.userData.originalColor !== undefined) {
c.material.color.setHex(c.userData.originalColor);
}
});
}
lockedCable = intersects[0].object;
lockedCable.material.color.setHex(0xffffff);
const clickedCable = intersects[0].object;
const cableId = clickedCable.userData.cableId;
const sameCables = getCablesById(cableId);
sameCables.forEach(c => {
c.material.color.setHex(0xffffff);
c.material.opacity = 1;
});
lockedCable = clickedCable;
lockedCableData = { ...clickedCable.userData };
setAutoRotate(false);
handleCableClick(intersects[0].object);
handleCableClick(clickedCable);
} else {
if (lockedCable) {
if (lockedCable.userData.originalColor !== undefined) {
lockedCable.material.color.setHex(lockedCable.userData.originalColor);
}
const prevCableId = lockedCable.userData.cableId;
const prevSameCables = getCablesById(prevCableId);
prevSameCables.forEach(c => {
if (c.userData.originalColor !== undefined) {
c.material.color.setHex(c.userData.originalColor);
}
});
lockedCable = null;
lockedCableData = null;
}
setAutoRotate(true);
clearCableSelection();
@@ -270,9 +307,13 @@ function animate() {
if (lockedCable) {
const pulse = (Math.sin(Date.now() * 0.003) + 1) * 0.5;
lockedCable.material.opacity = 0.6 + pulse * 0.4;
const glowIntensity = 0.7 + pulse * 0.3;
lockedCable.material.color.setRGB(glowIntensity, glowIntensity, glowIntensity);
const cableId = lockedCable.userData.cableId;
const sameCables = getCablesById(cableId);
sameCables.forEach(c => {
c.material.opacity = 0.6 + pulse * 0.4;
c.material.color.setRGB(glowIntensity, glowIntensity, glowIntensity);
});
}
renderer.render(scene, camera);
@@ -280,11 +321,16 @@ function animate() {
window.clearLockedCable = function() {
if (lockedCable) {
if (lockedCable.userData.originalColor !== undefined) {
lockedCable.material.color.setHex(lockedCable.userData.originalColor);
lockedCable.material.opacity = 1.0;
}
const cableId = lockedCable.userData.cableId;
const sameCables = getCablesById(cableId);
sameCables.forEach(c => {
if (c.userData.originalColor !== undefined) {
c.material.color.setHex(c.userData.originalColor);
c.material.opacity = 1.0;
}
});
lockedCable = null;
lockedCableData = null;
}
clearCableSelection();
};