# ng3d **Repository Path**: kingecg/ng3d ## Basic Information - **Project Name**: ng3d - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-09 - **Last Updated**: 2026-08-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Web 3D 数字孪生系统(ng3d) 基于 **Angular 22(Standalone + Signals)** 与 **Three.js** 的 Web 3D 数字孪生系统前端,实现了 「园区 → 楼宇 → 楼层 → 机房」多级空间路由、场景无缝切换、射线拾取、实时遥测驱动的状态着色与 CSS3D 式设备信息面板。 ## 快速开始 ```bash bun install # 安装依赖(含 three / @types/three) bun run start # 启动开发服务器 http://localhost:4200 bun run build # 生产构建 bun run test # 单元测试(Vitest) ``` > 注意:Angular 22 需要 Node.js ≥ 22.22.3。 ## 路由结构(懒加载) | 路由 | 场景 | | --- | --- | | `/twin` | 园区总览(CampusScene) | | `/twin/building/:buildingId` | 楼宇外观(BuildingScene) | | `/twin/building/:buildingId/floor/:floorId` | 楼层内部(FloorScene) | | `/twin/building/:buildingId/floor/:floorId/room/:roomId` | 机房/设备(RoomScene) | ## 交互操作 | 层级 | 3D 交互 | 说明 | | --- | --- | --- | | 园区 | 点击楼宇 | 相机推近 + **楼层逐层展开动画**,结束后自动进入楼宇详情 | | 楼宇 | 悬停/点击楼层切片 | 楼体按层切片,悬停高亮当前楼层,点击直接进入对应楼层 | | 楼层 | 悬停/点击房间 | 半透明房间外壳 + 描边,悬停增亮,点击进入机房 | | 机房 | 点击设备 | 机柜/空调可拾取,弹出**跟随设备的实时信息面板**;右侧列表可选中并聚焦 | 除 3D 交互外,各级场景左上角提供面包屑导航,右侧列表支持逐级下钻。 ## 核心架构 ``` src/app/ ├── core/ │ ├── models/ # 数据模型(Campus/Building/Floor/Room/Equipment/Telemetry) │ ├── three/ # 程序化模型构建器 + 资源释放工具 │ └── services/ │ ├── scene.service.ts # 单例:Renderer/Scene/Camera/动画循环/相机过渡/内存清理 │ ├── interaction.service.ts # Raycaster 射线拾取 → RxJS Observable(hover/click) │ ├── asset-manager.service.ts# glTF 加载器(缓存 + 进度 + 安全克隆) │ ├── transform.service.ts # 后端坐标 → 3D 场景坐标映射 │ ├── twin-data.service.ts # Mock 数据源(可替换为 HTTP 后端) │ └── realtime.service.ts # WebSocket 遥测模拟(可替换为真实连接) ├── shared/ │ ├── scene-page/ # 场景页基类(渲染器挂载、交互绑定、路由参数重建、统一清理) │ ├── breadcrumb/ # 层级面包屑导航 │ ├── device-panel/ # 跟随设备的 3D 信息面板(CSS3D 方案) │ └── loading-indicator/ # 场景加载指示 └── scenes/ # campus / building / floor / room 四个层级场景 ``` ## 关键设计 - **渲染器复用**:全局单例 `SceneService` 只创建一次 `WebGLRenderer` / `OrbitControls` / 光照 / 动画循环;路由切换时把 canvas 迁移到新场景容器,仅清空并重建场景内容,避免重复创建销毁与 多渲染循环叠加导致的泄漏。 - **Zone 外渲染**:渲染循环运行在 `NgZone.runOutsideAngular` 中,仅状态变更时通过信号触发变更检测。 - **相机过渡**:内置 easeInOutCubic 插值(flyTo),场景切换 900ms 平滑推近;园区点击楼宇时 先推近再播放**逐层展开动画**(楼层切片涟漪式升起回落),随后自动导航。 - **楼层切片模型**:楼体按楼层切成独立可拾取的区块(`floor-segment-{level}`),园区与楼宇场景 共用同一模型构建器,通过参数控制是否挂接楼层交互数据。 - **InstancedMesh 实例化**:机房机柜以单个 `InstancedMesh` 渲染(8 台 = 1 次 Draw Call), 射线拾取通过 `instanceId` 定位到具体设备。 - **数据驱动视觉**:遥测流(模拟 WebSocket,2.5s 间隔)驱动机柜 `setColorAt` 与设备 `emissive` 着色:正常(绿)/ 告警(橙)/ 故障(红 + 呼吸脉冲)。 - **内存防护**:场景卸载时递归释放 Geometry/Material/Texture,断开遥测订阅与每帧回调。 - **CSS3D 面板**:设备信息面板以真实 Angular 组件挂载于 3D 空间上方,渲染循环内(Zone 外) 直接更新 DOM transform 实现跟随,数据经 `@Input` 信号实时绑定。 ## 接入真实后端 1. `TwinDataService` 的各查询方法替换为 HTTP 调用(返回类型不变)。 2. `RealtimeService.connect()` 替换为 `WebSocket` 连接并 forward 消息。 3. 设备 `Equipment.modelUrl` 指向 glTF/glb 资源后,`AssetManager.loadModel` 自动加载并摆放; 缺省使用程序化占位模型。