Ver Fonte

Merge branch 'master' of https://github.com/usernamedd/zsis
ddddddi.

dengdx há 1 mês atrás
pai
commit
d0b81b4500
1 ficheiros alterados com 74 adições e 4 exclusões
  1. 74 4
      src/pages/view/components/viewers/stack.image.viewer.tsx

+ 74 - 4
src/pages/view/components/viewers/stack.image.viewer.tsx

@@ -313,11 +313,52 @@ export function adjustBrightnessAndContrast(currentViewportId: string) {
   }
 }
 
+/**
+ * 防抖工具函数
+ * @param func 要防抖的函数
+ * @param wait 等待时间(毫秒)
+ * @returns 防抖后的函数
+ */
+function debounce<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void {
+  let timeout: NodeJS.Timeout | null = null;
+  return (...args: Parameters<T>) => {
+    if (timeout) clearTimeout(timeout);
+    timeout = setTimeout(() => func(...args), wait);
+  };
+}
+
+function containImage(viewport:cornerstone.StackViewport) {
+    viewport.getRenderingEngine().resize(/* immediate */ true);
+    console.log(`使用 resetCamera方式`)
+    viewport.resetCamera({ resetPan: true, resetZoom: true }); // 重置 pan/zoom 到 contain
+    viewport.render();
+}
+
+/**
+ * 保持宽高比的图像适应函数
+ * 确保图像完全显示在容器内,同时保持原始宽高比(可能会有黑边)
+ * @param currentViewportId 当前视口ID
+ */
+export function fitImageWithAspectRatio(currentViewportId: string): void {
+  try {
+    console.log(`[fitImageWithAspectRatio] 重新适配大小`)
+    const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
+      .viewport as cornerstone.StackViewport;
+
+    if (!viewport) {
+      console.warn(`[fitImageWithAspectRatio] Viewport not found: ${currentViewportId}`);
+      return;
+    }
+    containImage(viewport)
+
+  } catch (error) {
+    console.error(`[fitImageWithAspectRatio] Error fitting image with aspect ratio:`, error);
+  }
+}
+
 export function fitImageSize(currentViewportId: string) {
-  const viewport = cornerstone.getEnabledElementByViewportId(currentViewportId)
-    .viewport as cornerstone.StackViewport;
-  viewport.resetCamera();
-  viewport.render();
+  // 使用新的保持宽高比的适应函数
+  fitImageWithAspectRatio(currentViewportId);
 }
 
 export function deleteSelectedMark(currentViewportId: string): void {
@@ -1371,6 +1412,9 @@ const StackViewer = ({
         // 4. 设置图像栈,包含超时保护
         await safeSetStack(viewport, imageUrls, imageIndex);
 
+        // 5. 图像加载完成后,自动应用保持宽高比的适应
+        fitImageWithAspectRatio(viewportId);
+
         console.log(`重新加载图像----结束`);
 
       } catch (error) {
@@ -1398,6 +1442,32 @@ const StackViewer = ({
     setup();
   }, [elementRef, imageIndex, viewportId, renderingEngineId, imageUrls[0]]);
 
+  // 监听容器大小变化,自动保持宽高比
+  useEffect(() => {
+    if (!elementRef.current) return;
+
+    // 创建防抖的适应函数
+    const debouncedFit = debounce(() => {
+      // console.log(`容器大小变化了---------`)
+      requestAnimationFrame(() => {
+        fitImageWithAspectRatio(viewportId);
+      });
+
+    }, 100);
+
+    // 创建ResizeObserver监听容器大小变化
+    const resizeObserver = new ResizeObserver(debouncedFit);
+    resizeObserver.observe(elementRef.current);
+
+    console.log(`[StackViewer] ResizeObserver attached to viewport: ${viewportId}`);
+
+    // 清理函数
+    return () => {
+      resizeObserver.disconnect();
+      console.log(`[StackViewer] ResizeObserver disconnected from viewport: ${viewportId}`);
+    };
+  }, [viewportId]);
+
   // 在渲染期间检查错误状态,如果有错误则抛出
   // 这样 Error Boundary 就能捕获到异步错误了
   if (renderError) {