webgl-error-timing-analysis.md 3.1 KB

WebGL 错误仅在切换胶片时出现的原因分析

现象

  • 拖拽图像时:没有 WebGL 错误
  • 切换胶片时:出现 OES_texture_float_linear 错误

根本原因分析

1. React Key 修复的副作用

我们刚刚添加了 key={currentFilm.id}-${indexOfCell},这导致:

// 切换胶片时的组件生命周期变化
胶片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 的扩展检查机制

// 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:忽略这个警告(推荐)

// 这是一个良性警告,不影响功能
// Cornerstone.js 会自动降级到兼容的渲染模式

方案2:抑制特定的 console 输出

// 如果确实需要减少日志噪音
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]);