diff --git a/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedAiWhiteBackgroundPanel.test.tsx b/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedAiWhiteBackgroundPanel.test.tsx index da11e130..cfeed57d 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedAiWhiteBackgroundPanel.test.tsx +++ b/furniture-3d-system/src/app/intake/non-integrated/NonIntegratedAiWhiteBackgroundPanel.test.tsx @@ -153,6 +153,12 @@ describe("NonIntegratedAiWhiteBackgroundPanel", () => { fireEvent.click(screen.getByRole("button", { name: "放大原图" })); expect(previewImage).toHaveStyle({ transform: "scale(1.25)" }); + fireEvent.wheel(lightbox, { deltaY: -100 }); + expect(previewImage).toHaveStyle({ transform: "scale(1.5)" }); + + fireEvent.wheel(lightbox, { deltaY: 100 }); + expect(previewImage).toHaveStyle({ transform: "scale(1.25)" }); + fireEvent.click(screen.getByRole("button", { name: "重置原图缩放" })); expect(previewImage).toHaveStyle({ transform: "scale(1)" }); diff --git a/furniture-3d-system/src/app/intake/non-integrated/workspaces/ai-white-background/NonIntegratedAiWhiteBackgroundPanel.tsx b/furniture-3d-system/src/app/intake/non-integrated/workspaces/ai-white-background/NonIntegratedAiWhiteBackgroundPanel.tsx index a87acb5c..dc0c7e81 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/workspaces/ai-white-background/NonIntegratedAiWhiteBackgroundPanel.tsx +++ b/furniture-3d-system/src/app/intake/non-integrated/workspaces/ai-white-background/NonIntegratedAiWhiteBackgroundPanel.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useState } from "react"; +import { type WheelEvent, useEffect, useState } from "react"; import { AlertCircle, ImageIcon, @@ -179,6 +179,8 @@ function getTargetFinishLabel(finish: AiWhiteBackgroundTargetFinishOption) { const AI_WHITE_BACKGROUND_PREVIEW_ZOOM_MIN = 0.5; const AI_WHITE_BACKGROUND_PREVIEW_ZOOM_MAX = 3; const AI_WHITE_BACKGROUND_PREVIEW_ZOOM_STEP = 0.25; +const AI_WHITE_BACKGROUND_PREVIEW_WHEEL_ZOOM_FACTOR = + AI_WHITE_BACKGROUND_PREVIEW_ZOOM_STEP / 100; function formatPreviewZoom(value: number) { return `${Math.round(value * 100)}%`; @@ -197,6 +199,7 @@ function AiWhiteBackgroundImageLightbox({ zoom, onZoomIn, onZoomOut, + onWheelZoom, onResetZoom, onClose, }: { @@ -205,6 +208,7 @@ function AiWhiteBackgroundImageLightbox({ zoom: number; onZoomIn: () => void; onZoomOut: () => void; + onWheelZoom: (deltaY: number) => void; onResetZoom: () => void; onClose: () => void; }) { @@ -219,6 +223,16 @@ function AiWhiteBackgroundImageLightbox({ return () => document.removeEventListener("keydown", handleKeyDown); }, [onClose]); + const handleWheelZoom = (event: WheelEvent) => { + if (Math.abs(event.deltaY) < 0.5) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + onWheelZoom(event.deltaY); + }; + return (
{ + const adjustPreviewZoom = (delta: number) => { setPreviewZoom((current) => - clampPreviewZoom( - current + direction * AI_WHITE_BACKGROUND_PREVIEW_ZOOM_STEP, - ), + clampPreviewZoom(current + delta), ); }; + const zoomInlinePreview = (direction: 1 | -1) => { + adjustPreviewZoom(direction * AI_WHITE_BACKGROUND_PREVIEW_ZOOM_STEP); + }; + const zoomPreviewWithWheel = (deltaY: number) => { + adjustPreviewZoom(-deltaY * AI_WHITE_BACKGROUND_PREVIEW_WHEEL_ZOOM_FACTOR); + }; return (
@@ -783,6 +802,7 @@ export default function NonIntegratedAiWhiteBackgroundPanel({ zoom={previewZoom} onZoomIn={() => zoomInlinePreview(1)} onZoomOut={() => zoomInlinePreview(-1)} + onWheelZoom={zoomPreviewWithWheel} onResetZoom={() => setPreviewZoom(1)} onClose={closeInlinePreview} />