# WebGL 错误仅在切换胶片时出现的原因分析 ## 现象 - **拖拽图像时**:没有 WebGL 错误 - **切换胶片时**:出现 `OES_texture_float_linear` 错误 ## 根本原因分析 ### 1. React Key 修复的副作用 我们刚刚添加了 `key={currentFilm.id}-${indexOfCell}`,这导致: ```typescript // 切换胶片时的组件生命周期变化 胶片1 → 胶片2: - 旧组件卸载: ViewportContainer key="1-0" → unmount - 新组件创建: ViewportContainer key="2-0" → mount ``` ### 2. 渲染引擎初始化时机差异 #### 拖拽时的执行路径: ``` 1. 组件已完全初始化 (useEffect 已执行) 2. 渲染引擎稳定运行 3. viewport 已创建并稳定 4. handleDrop → loadImage('drag') 5. 在已有的、稳定的 WebGL 上下文中操作 ``` #### 切换胶片时的执行路径: ``` 1. React 创建新组件实例 (key 不同) 2. useEffect 开始执行: - 创建新的渲染引擎: `renderingEngine-${currentFilm.id}` - 初始化 WebGL 上下文 - 创建新的 viewport 3. 同时 useEffect([imageId, stackViewport]) 也触发: - loadImage('props') 立即执行 - 在新创建的、可能不稳定的 WebGL 上下文中操作 ``` ### 3. WebGL 上下文状态差异 #### 稳定的 WebGL 上下文 (拖拽时) - 扩展已加载和验证 - 资源已分配 - 状态机稳定 #### 新创建的 WebGL 上下文 (切换胶片时) - 扩展正在检查和加载 - 某些扩展可能检查失败但不影响基本功能 - 状态机可能不稳定 ### 4. Cornerstone.js 的扩展检查机制 ```typescript // Cornerstone 在新的 WebGL 上下文中会重新检查所有扩展 // 包括 OES_texture_float_linear // 如果检查失败,会记录警告但继续执行 ``` ## 证据支持 ### 错误堆栈证实了这个分析: ``` loadImage @ DcmCell.tsx:56 // 我们的 loadImage 函数 loadImageFromProps @ DcmCell.tsx:183 // useEffect 中的调用,不是拖拽 ``` 这确认错误来自切换胶片时的自动加载,而不是拖拽。 ## 结论 1. **错误是良性的**:这是 Cornerstone.js 在新 WebGL 上下文中检查扩展时的警告 2. **功能正常**:图像仍然可以正常加载和显示 3. **原因是我们的修复**:React Key 强制重新创建组件暴露了这个检查过程 ## 建议处理方式 ### 方案1:忽略这个警告(推荐) ```typescript // 这是一个良性警告,不影响功能 // Cornerstone.js 会自动降级到兼容的渲染模式 ``` ### 方案2:抑制特定的 console 输出 ```typescript // 如果确实需要减少日志噪音 const originalWarn = console.warn; console.warn = (...args) => { if (args[0] && args[0].includes('OES_texture_float_linear')) { return; // 静默这个特定警告 } originalWarn.apply(console, args); }; ``` ### 方案3:延迟图像加载 ```typescript // 确保 WebGL 上下文完全初始化后再加载图像 useEffect(() => { const loadImageFromProps = async () => { if (!stackViewport) return; // 给 WebGL 上下文一点初始化时间 await new Promise(resolve => setTimeout(resolve, 100)); // 然后正常加载 // ... }; }, [imageId, stackViewport]);