feat: 处理窗口resize
This commit is contained in:
parent
d09d852207
commit
dff24401bf
|
@ -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];
|
||||
|
|
|
@ -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<string[]>();
|
||||
const renderingEngineRef = useRef<RenderingEngine>();
|
||||
const volumeId = SeriesInstanceUID;
|
||||
const toolGroupStackId = "STACK_TOOL_GROUP:" + SeriesInstanceUID;
|
||||
|
||||
useMultiResizeObserver(
|
||||
[
|
||||
stackViewportRef,
|
||||
volumeViewport1Ref,
|
||||
volumeViewport2Ref,
|
||||
volumeViewport3Ref,
|
||||
],
|
||||
() => renderingEngineRef.current?.resize()
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
cornerstoneTools.addTool(StackScrollMouseWheelTool);
|
||||
|
@ -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 (
|
||||
<div className="w-full h-full flex flex-col">
|
||||
<div className="flex-shrink-0 border-b border-secondary">
|
||||
|
@ -315,15 +295,19 @@ export const Viewer = () => {
|
|||
</ResizablePanel>
|
||||
<ResizableHandle withHandle />
|
||||
<ResizablePanel defaultSize={50}>
|
||||
<div
|
||||
className="w-full h-1/3 border-b border-1 border-secondary"
|
||||
ref={volumeViewport1Ref}
|
||||
/>
|
||||
<div
|
||||
className="w-full h-1/3 border-b border-1 border-secondary"
|
||||
ref={volumeViewport2Ref}
|
||||
/>
|
||||
<div className="w-full h-1/3" ref={volumeViewport3Ref} />
|
||||
<ResizablePanelGroup direction="vertical" className="w-full h-full">
|
||||
<ResizablePanel defaultSize={1 / 3}>
|
||||
<div className="h-full" ref={volumeViewport1Ref} />
|
||||
</ResizablePanel>
|
||||
<ResizableHandle withHandle />
|
||||
<ResizablePanel defaultSize={1 / 3}>
|
||||
<div className="h-full" ref={volumeViewport2Ref} />
|
||||
</ResizablePanel>
|
||||
<ResizableHandle withHandle />
|
||||
<ResizablePanel defaultSize={1 / 3}>
|
||||
<div className="h-full" ref={volumeViewport3Ref} />
|
||||
</ResizablePanel>
|
||||
</ResizablePanelGroup>
|
||||
</ResizablePanel>
|
||||
</ResizablePanelGroup>
|
||||
</div>
|
||||
|
|
41
apps/desktop/src/pages/Viewer/useMultiResizeObserver.tsx
Normal file
41
apps/desktop/src/pages/Viewer/useMultiResizeObserver.tsx
Normal file
|
@ -0,0 +1,41 @@
|
|||
import { useEffect, RefObject } from "react";
|
||||
|
||||
type ResizeObserverCallback = () => void;
|
||||
|
||||
/**
|
||||
* 自定义 Hook,用于监听多个 Ref 对象的尺寸变化
|
||||
* @param refs - 要监听的 Ref 对象数组
|
||||
* @param callback - 尺寸变化时调用的回调函数
|
||||
*/
|
||||
function useMultiResizeObserver(
|
||||
refs: Array<RefObject<Element>>,
|
||||
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;
|
Loading…
Reference in New Issue
Block a user