From dff24401bf193963e8281ad1304edf2db7640943 Mon Sep 17 00:00:00 2001 From: mozzie Date: Thu, 19 Sep 2024 15:00:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A4=84=E7=90=86=E7=AA=97=E5=8F=A3res?= =?UTF-8?q?ize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/Viewer/MprViewer/index.config.tsx | 8 +- apps/desktop/src/pages/Viewer/index.tsx | 94 ++++++++----------- .../pages/Viewer/useMultiResizeObserver.tsx | 41 ++++++++ 3 files changed, 87 insertions(+), 56 deletions(-) create mode 100644 apps/desktop/src/pages/Viewer/useMultiResizeObserver.tsx diff --git a/apps/desktop/src/pages/Viewer/MprViewer/index.config.tsx b/apps/desktop/src/pages/Viewer/MprViewer/index.config.tsx index a0184df..d522fb8 100644 --- a/apps/desktop/src/pages/Viewer/MprViewer/index.config.tsx +++ b/apps/desktop/src/pages/Viewer/MprViewer/index.config.tsx @@ -5,6 +5,11 @@ export type ViewportId = "CT_AXIAL" | "CT_SAGITTAL" | "CT_CORONAL"; export const viewportId1: ViewportId = "CT_AXIAL"; export const viewportId2: ViewportId = "CT_SAGITTAL"; export const viewportId3: ViewportId = "CT_CORONAL"; +export const viewportIds: ViewportId[] = [ + viewportId1, + viewportId2, + viewportId3, +]; export const viewportColors = { [viewportId1]: "rgb(200, 0, 0)", @@ -34,7 +39,8 @@ export const viewportReferenceLineSlabThicknessControlsOn = [ export const volumeName = "CT_VOLUME_ID"; // Id of the volume less loader prefix export const volumeLoaderScheme = "cornerstoneStreamingImageVolume"; // Loader id which defines which volume loader to use export const volumeId = `${volumeLoaderScheme}:${volumeName}`; // VolumeId with loader id + volume id -export const toolGroupMprId = "toolMprNo1"; +export const toolGroupMprId = "toolMpr"; +export const toolGroupStackId = "toolStack"; export function getReferenceLineColor(vpId: ViewportId) { return viewportColors[vpId]; diff --git a/apps/desktop/src/pages/Viewer/index.tsx b/apps/desktop/src/pages/Viewer/index.tsx index 916f045..c54d3d0 100644 --- a/apps/desktop/src/pages/Viewer/index.tsx +++ b/apps/desktop/src/pages/Viewer/index.tsx @@ -26,15 +26,14 @@ import { getReferenceLineDraggableRotatable, getReferenceLineSlabThicknessControlsOn, toolGroupMprId, - viewportId1, - viewportId2, - viewportId3, + toolGroupStackId, + viewportIds, } from "./MprViewer/index.config"; -import setCtTransferFunctionForVolumeActor from "./MprViewer/CornerstoneDicomLoader/setCtTransferFunctionForVolumeActor"; import { Slider } from "@/components/ui/slider"; import { stackViewportId } from "./StackViewer/index.config"; import { ToolBarMenu } from "./ToolBarMenu"; import { Model3DViewer } from "./ModelViewer"; +import useMultiResizeObserver from "./useMultiResizeObserver"; const { ToolGroupManager, @@ -69,7 +68,16 @@ export const Viewer = () => { const [imageIds, setImageIds] = useState(); const renderingEngineRef = useRef(); const volumeId = SeriesInstanceUID; - const toolGroupStackId = "STACK_TOOL_GROUP:" + SeriesInstanceUID; + + useMultiResizeObserver( + [ + stackViewportRef, + volumeViewport1Ref, + volumeViewport2Ref, + volumeViewport3Ref, + ], + () => renderingEngineRef.current?.resize() + ); useEffect(() => { cornerstoneTools.addTool(StackScrollMouseWheelTool); @@ -90,7 +98,7 @@ export const Viewer = () => { SeriesInstanceUID, wadoRsRoot, }); - + // 这一步会对imageIds进行排序,如果不排序imageIds会错误乱,stackViewport顺序会错误 const volume = await volumeLoader.createAndCacheVolume( SeriesInstanceUID, @@ -102,7 +110,7 @@ export const Viewer = () => { const volumeViewportInput: PublicViewportInput[] = [ { - viewportId: viewportId1, + viewportId: viewportIds[0], type: ViewportType.ORTHOGRAPHIC, element: volumeViewport1Ref.current, defaultOptions: { @@ -111,7 +119,7 @@ export const Viewer = () => { }, }, { - viewportId: viewportId2, + viewportId: viewportIds[1], type: ViewportType.ORTHOGRAPHIC, element: volumeViewport2Ref.current, defaultOptions: { @@ -120,7 +128,7 @@ export const Viewer = () => { }, }, { - viewportId: viewportId3, + viewportId: viewportIds[2], type: ViewportType.ORTHOGRAPHIC, element: volumeViewport3Ref.current, defaultOptions: { @@ -151,13 +159,11 @@ export const Viewer = () => { const toolGroupMpr = ToolGroupManager.createToolGroup(toolGroupMprId); if (toolGroupMpr) { - toolGroupMpr.addViewport(viewportId1, renderingEngineId); - toolGroupMpr.addViewport(viewportId2, renderingEngineId); - toolGroupMpr.addViewport(viewportId3, renderingEngineId); + viewportIds.forEach((vp) => + toolGroupMpr.addViewport(vp, renderingEngineId) + ); toolGroupMpr.addTool(ZoomTool.toolName); - toolGroupMpr.setToolActive(ZoomTool.toolName, { - bindings: [{ mouseButton: MouseBindings.Secondary }], - }); + toolGroupMpr.addTool(WindowLevelTool.toolName); toolGroupMpr.addTool(StackScrollMouseWheelTool.toolName); toolGroupMpr.addTool(CrosshairsTool.toolName, { getReferenceLineColor, @@ -165,12 +171,13 @@ export const Viewer = () => { getReferenceLineDraggableRotatable, getReferenceLineSlabThicknessControlsOn, }); + toolGroupMpr.setToolActive(ZoomTool.toolName, { + bindings: [{ mouseButton: MouseBindings.Secondary }], + }); toolGroupMpr.setToolActive(CrosshairsTool.toolName, { bindings: [{ mouseButton: MouseBindings.Primary }], }); toolGroupMpr.setToolActive(StackScrollMouseWheelTool.toolName); - - toolGroupMpr.addTool(WindowLevelTool.toolName); toolGroupMpr.setToolActive(WindowLevelTool.toolName, { bindings: [{ mouseButton: MouseBindings.Auxiliary }], }); @@ -195,12 +202,8 @@ export const Viewer = () => { await setVolumesForViewports( renderingEngineRef.current, [{ volumeId: SeriesInstanceUID }], - [viewportId1, viewportId2, viewportId3] + viewportIds ); - - // 默认windowWidtth - // const { windowCenter, windowWidth } = - // volumeRef.current.cornerstoneImageMetaData; }; initCornerstone(() => { @@ -208,10 +211,6 @@ export const Viewer = () => { }); return () => { - // renderingEngineRef.current?.disableElement(stackViewportId); - // renderingEngineRef.current?.disableElement(viewportId1); - // renderingEngineRef.current?.disableElement(viewportId2); - // renderingEngineRef.current?.disableElement(viewportId3); cache.purgeCache(); ToolGroupManager.destroy(); renderingEngineRef.current?.destroy(); @@ -221,7 +220,7 @@ export const Viewer = () => { cornerstoneTools.removeTool(WindowLevelTool); cornerstoneTools.removeTool(ZoomTool); }; - }, [SeriesInstanceUID, StudyInstanceUID, toolGroupStackId, volumeId]); + }, [SeriesInstanceUID, StudyInstanceUID, volumeId]); const onChangeIndex = (value: number[]) => setIndex(value[0]); @@ -253,25 +252,6 @@ export const Viewer = () => { } }, [index]); - useEffect(() => { - const container = stackViewportRef.current; - if (!container) return; - let resizeTimeout: NodeJS.Timeout | null = null; - const resizeObserver = new ResizeObserver(() => { - if (resizeTimeout) clearTimeout(resizeTimeout); - resizeTimeout = setTimeout( - () => renderingEngineRef.current?.resize(), - 100 - ); - }); - resizeObserver.observe(container); - return () => { - if (resizeTimeout) clearTimeout(resizeTimeout); - resizeObserver.unobserve(container); - resizeObserver.disconnect(); - }; - }, []); - return (
@@ -315,15 +295,19 @@ export const Viewer = () => { -
-
-
+ + +
+ + + +
+ + + +
+ +
diff --git a/apps/desktop/src/pages/Viewer/useMultiResizeObserver.tsx b/apps/desktop/src/pages/Viewer/useMultiResizeObserver.tsx new file mode 100644 index 0000000..8fdc35b --- /dev/null +++ b/apps/desktop/src/pages/Viewer/useMultiResizeObserver.tsx @@ -0,0 +1,41 @@ +import { useEffect, RefObject } from "react"; + +type ResizeObserverCallback = () => void; + +/** + * 自定义 Hook,用于监听多个 Ref 对象的尺寸变化 + * @param refs - 要监听的 Ref 对象数组 + * @param callback - 尺寸变化时调用的回调函数 + */ +function useMultiResizeObserver( + refs: Array>, + callback: ResizeObserverCallback +) { + useEffect(() => { + const elements = refs + .map((ref) => ref.current) + .filter((el): el is Element => el !== null); + + if (elements.length === 0) return; + + let resizeTimeout: NodeJS.Timeout | null = null; + const resizeObserver = new ResizeObserver(() => { + if (resizeTimeout) clearTimeout(resizeTimeout); + resizeTimeout = setTimeout(callback, 100); + }); + + elements.forEach((element) => { + resizeObserver.observe(element); + }); + + return () => { + if (resizeTimeout) clearTimeout(resizeTimeout); + elements.forEach((element) => { + resizeObserver.unobserve(element); + }); + resizeObserver.disconnect(); + }; + }, [refs, callback]); +} + +export default useMultiResizeObserver;