React函数组件使用Cornerstone栈滚动工具时如何获取currentImageIdIndex
Cornerstone 图像栈滚动索引获取方案
你不需要直接操作DOM绑定原生事件,使用Cornerstone Tools官方提供的事件API即可,监听器需要在视口栈状态初始化完成后注册,组件卸载时要移除监听器避免内存泄漏。
核心实现逻辑
- 监听事件:使用
cornerstonetoolsstackscroll内置事件,滚轮滚动、拖拽切换图像时都会触发该事件 - 注册时机:必须在
addToolState完成栈状态挂载之后注册,否则事件无法正常绑定 - 取值方式:直接从Cornerstone的工具状态中读取
currentImageIdIndex,保证和内部状态完全同步,不需要自行计算索引
具体代码修改
1. 新增滚动事件处理回调
把这个方法放到组件内,注意用useCallback包裹避免引用变化导致监听器无法正确移除:
const handleStackScroll = useCallback(() => { if (!viewerRef.current) return; // 从Cornerstone状态中读取当前栈数据 const stackState = cornerstoneTools.getToolState(viewerRef.current, 'stack'); const currentStack = stackState?.data?.[0]; if (currentStack) { const currentImageIdIndex = currentStack.currentImageIdIndex; // 此处编写索引获取后的业务逻辑,比如透传给父组件、更新本地展示状态等 console.log('当前展示图像索引:', currentImageIdIndex); } }, []);
2. 修正原有异步逻辑问题
你原来的代码中Promise.all没有等待执行完成就初始化栈,会导致mediaArray为空报错,需要把displayStack改成async函数,等所有imageId生成、首图加载完成后再初始化栈、绑定事件:
const displayStack = async (stackMediaArray) => { let mediaArray = []; // 等待所有图像的imageId生成完成 await Promise.all( stackMediaArray.map((mediaObject) => { return new Promise((resolve, reject) => { let imageBuffer = base64StringToArrayBuffer(mediaObject.buffer); const imageId = cornerstoneFileImageLoader.fileManager.addBuffer(imageBuffer); mediaArray.push(imageId); resolve(mediaObject); }).catch(console.error); }) ); // 定义栈初始状态 const stack = { currentImageIdIndex: 0, imageIds: mediaArray, }; // 等待首图加载完成后初始化视口栈 const firstImage = await cornerstone.loadAndCacheImage(mediaArray[0]); cornerstone.displayImage(viewerRef.current, firstImage); cornerstoneTools.addStackStateManager(viewerRef.current, ["stack"]); cornerstoneTools.addToolState(viewerRef.current, "stack", stack); // 栈状态初始化完成后,注册滚动事件监听器 cornerstoneTools.addEventListener( viewerRef.current, "cornerstonetoolsstackscroll", handleStackScroll ); setCornerstoneTools(); };
3. 增加useEffect清理逻辑
在useEffect的返回函数中移除事件监听器、销毁cornerstone实例,避免内存泄漏:
useEffect(() => { if (!viewerRef.current) return; initializeCornerstone(); displayStack(props.stackMediaArray); // 组件卸载时执行清理 return () => { cornerstoneTools.removeEventListener( viewerRef.current, "cornerstonetoolsstackscroll", handleStackScroll ); cornerstone.disable(viewerRef.current); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [viewerRef]);
注意事项
- 不要自行维护索引值:Cornerstone内部会处理循环滚动、边界判断等逻辑,直接从工具状态读取的索引永远是准确的
- 不需要绑定DOM原生事件:上述方案全程使用Cornerstone官方事件API,符合你不直接操作DOM的需求
- 两种滚动触发方式都能捕获:不管是鼠标滚轮触发
StackScrollMouseWheelTool,还是鼠标拖拽触发StackScrollTool,事件都会正常触发
内容的提问来源于stack exchange,提问作者Radespy
相关产品推荐
相关产品推荐

