Files
planet/.sisyphus/plans/earth-architecture-refactor.md

4.2 KiB

地球3D可视化架构重构计划

背景

当前 frontend/public/earth 3D地球可视化系统基于 Three.js 构建,未来需要迁移到 Unreal Engine (Cesium)。为降低迁移成本,需要提前做好逻辑与渲染分离的架构设计。

目标

  • 将线缆高亮逻辑与渲染实现分离
  • 保持交互逻辑可复用,只需重写渲染层
  • 为后续迁移到 UE/Cesium 做好准备

已完成

1. 状态枚举定义 (constants.js)

export const CABLE_STATE = {
  NORMAL: 'normal',
  HOVERED: 'hovered',
  LOCKED: 'locked'
};

2. 线缆状态管理 (cables.js - 数据层)

const cableStates = new Map();

export function getCableState(cableId) { ... }
export function setCableState(cableId, state) { ... }
export function clearAllCableStates() { ... }
export function getCableStateInfo() { ... }

3. 逻辑层调用 (main.js)

// 悬停
setCableState(cable.userData.cableId, CABLE_STATE.HOVERED);

// 锁定
setCableState(cableId, CABLE_STATE.LOCKED);

// 恢复
setCableState(cableId, CABLE_STATE.NORMAL);
clearAllCableStates();

// 清除锁定时
clearLockedObject() {
  hoveredCable = null;
  clearAllCableStates();
  ...
}

4. 渲染层 (main.js - applyCableVisualState)

function applyCableVisualState() {
  const allCables = getCableLines();
  const pulse = (Math.sin(Date.now() * CABLE_CONFIG.pulseSpeed) + 1) * 0.5;
  
  allCables.forEach(c => {
    const cableId = c.userData.cableId;
    const state = getCableState(cableId);
    
    switch (state) {
      case CABLE_STATE.LOCKED:
        // 呼吸效果 + 白色
        c.material.opacity = CABLE_CONFIG.lockedOpacityMin + pulse * CABLE_CONFIG.pulseCoefficient;
        c.material.color.setRGB(1, 1, 1);
        break;
      case CABLE_STATE.HOVERED:
        // 白色高亮
        c.material.opacity = 1;
        c.material.color.setRGB(1, 1, 1);
        break;
      case CABLE_STATE.NORMAL:
      default:
        if (lockedObjectType === 'cable' && lockedObject) {
          // 其他线缆变暗
          c.material.opacity = CABLE_CONFIG.otherOpacity;
          ...
        } else {
          // 恢复原始
          c.material.opacity = 1;
          c.material.color.setHex(c.userData.originalColor);
        }
    }
  });
}

待完成

Phase 1: 完善状态配置 (constants.js)

export const CABLE_CONFIG = {
  lockedOpacityMin: 0.6,
  lockedOpacityMax: 1.0,
  otherOpacity: 0.5,
  otherBrightness: 0.6,
  pulseSpeed: 0.003,
  pulseCoefficient: 0.4,
  // 未来可扩展
  // lockedLineWidth: 3,
  // normalLineWidth: 1,
};

Phase 2: 卫星状态管理 (satellites.js)

参考线缆状态管理,为卫星添加类似的状态枚举和状态管理函数:

export const SATELLITE_STATE = {
  NORMAL: 'normal',
  HOVERED: 'hovered',
  LOCKED: 'locked'
};

卫星数据源说明

  • 当前使用: CelesTrak (https://celestrak.org) - 免费,无需认证
  • 后续计划: Space-Track.org (https://space-track.org) - 需要认证,数据更权威
  • 迁移时只需修改 satellites.js 中的数据获取逻辑,状态管理和渲染逻辑不变

Phase 3: 统一渲染接口

将所有对象的渲染逻辑抽象为一个统一的渲染函数:

function applyObjectVisualState() {
  applyCableVisualState();
  applySatelliteVisualState();
  applyLandingPointVisualState();
}

Phase 4: UE 迁移准备

迁移到 Unreal Engine 时:

  1. 保留 constants.js 中的枚举和配置
  2. 保留 cables.js 中的数据层和状态管理
  3. 保留 main.js 中的交互逻辑
  4. 仅重写 applyCableVisualState() 等渲染函数

架构原则

  1. 状态与渲染分离 - 对象状态由数据层管理,渲染层只负责根据状态更新视觉效果
  2. 逻辑可复用 - 交互逻辑(点击、悬停、锁定)在迁移时应直接复用
  3. 渲染可替换 - 渲染实现可以针对不同引擎重写,不影响逻辑层

文件变更记录

日期 文件 变更
2026-03-19 constants.js 新增 CABLE_STATE 枚举
2026-03-19 cables.js 新增状态管理函数
2026-03-19 main.js 使用状态管理,抽象 applyCableVisualState()