# 实现方案 - 2026-05-07-16-53-23 ## 修改目标 修复 3D 模型在细节档位切换和鼠标旋转时的中心漂移问题,并完善右下角坐标系联动和按钮样式。 ## 涉及路径 - `WebSite/src/components/ProjectLibrary.tsx` ## 技术路线 ### 1. 分离 Three.js 渲染容器和 React overlay 当前 `NativeStlViewer` 会对 `containerRef.current.innerHTML = ''`,容易把 React overlay 或其他子节点一起清掉。改为: - `viewportRef`:只用于挂载 Three.js canvas。 - 外层 React 容器保留进度条、状态条、右下角坐标系等 overlay。 - 清理时只清理 `viewportRef` 内的 canvas。 ### 2. 修正模型重载后的中心与缩放 模型加载完成后: - 先把所有 mesh 加入 `pivotGroup`。 - 基于 `pivotGroup` 的整体包围盒计算 `center` 和 `size`。 - 将所有 mesh geometry 统一平移 `-center`,保证拼装后的整体中心落在局部原点。 - 使用 `pivotGroup.rotation` 和 `pivotGroup.scale`,使用 `poseGroup.position` 做平移。 - 每次切换细节档位时重建模型,但继承同一份 `modelPose`,并确保新模型仍以整体中心为 pivot。 ### 3. 鼠标拖拽围绕模型中心旋转 - 鼠标左键拖拽只更新 `rotateX/rotateY`,不改变 `translateX/Y/Z`。 - 旋转继续作用在 `pivotGroup`,而不是同时承担平移的 group。 - 对 `poseRef.current` 做统一 clamp,保持鼠标、滑块、快捷按钮状态一致。 ### 4. 坐标系随位姿同步旋转 新增一个轻量 SVG 坐标轴组件: - 根据 `rotateX/Y/Z` 构造 Three.js `Euler` 和 `Matrix4`。 - 将 X/Y/Z 三个单位轴向量通过旋转矩阵变换后投影到 2D。 - 在右下角 SVG 中绘制红色 X、绿色 Y、蓝色 Z 三条轴。 - 继续显示 X/Y/Z 当前角度数值。 ### 5. 调整按钮颜色 - 将 `重置平移缩放位姿` 的文字颜色改为 `text-blue-600 hover:text-blue-700`,与 `重置旋转位姿` 一致。 ## 数据流或交互流程 1. 用户拖拽鼠标或点击位姿按钮。 2. `modelPose` 更新并 clamp。 3. `NativeStlViewer` 的动画循环读取 `poseRef.current`。 4. `poseGroup` 只应用平移,`pivotGroup` 只应用旋转和缩放。 5. 右下角坐标轴组件读取同一份 `pose`,同步更新方向。 6. 切换模型显示细节档时重新请求 STL preview,但模型仍以整体包围盒中心作为 pivot。 ## 兼容性与回滚方案 - 修改仅影响项目库 3D 模型页,不修改 DICOM 后端和 mask 导出。 - 若 SVG 坐标轴表现不佳,可回滚为静态坐标轴加角度文本。 - 若新的 viewportRef 清理方式导致 canvas 不显示,可回滚为原始 containerRef,但必须避免清掉 overlay。 ## 预计文件变更 - `WebSite/src/components/ProjectLibrary.tsx` - 新增 `OrientationGizmo`。 - `NativeStlViewer` 改用 `viewportRef`。 - 调整模型中心化和清理逻辑。 - 调整重置按钮样式。 ## 人工审核状态 - 本次免二次确认,方案写入后直接执行。 ## 执行结果 - 已在 `WebSite/server.ts` 为 STL preview 增加全量包围盒 `bounds`。 - 已在 `WebSite/src/components/ProjectLibrary.tsx` 使用所有可见 STL 的稳定全量包围盒计算整体中心和缩放基准。 - 已将右下角静态坐标轴替换为基于 `rotateX/Y/Z` 投影的动态 SVG 坐标轴。 - 已统一 `重置旋转位姿` 与 `重置平移缩放位姿` 的字体颜色。