From a8e5408136e18494cf87f2c94de8add56dc14558 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 29 Dec 2025 23:43:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B0=BA=E5=AF=B8=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E5=8A=9F=E8=83=BD=EF=BC=9A=E6=B7=BB=E5=8A=A0=E6=AF=94?= =?UTF-8?q?=E4=BE=8B=E9=80=89=E6=8B=A9=E5=92=8C=E4=BF=AE=E5=A4=8D=E5=8E=9F?= =?UTF-8?q?=E5=9B=BE=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加快捷比例选择功能(智能、21:9、16:9、3:2、4:3、1:1、3:4、2:3、9:16) - 选择比例后,输入宽度时高度自动根据比例计算 - 优化左右对比布局,减少空白,画布显示更大 - 修复点击确认调整后原图消失的问题,保持原图一直显示 - 优化工具栏布局,尺寸调整模式下显示专用工具栏 --- components/image-annotator.tsx | 283 ++++++++++++++++++++++----------- 1 file changed, 194 insertions(+), 89 deletions(-) diff --git a/components/image-annotator.tsx b/components/image-annotator.tsx index cb2d50eaa..d4dc37e5b 100644 --- a/components/image-annotator.tsx +++ b/components/image-annotator.tsx @@ -78,9 +78,68 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel }: ImageAnnotator const [resizeImagePosition, setResizeImagePosition] = useState<{ x: number; y: number }>({ x: 0, y: 0 }); const [isDraggingResize, setIsDraggingResize] = useState(false); const [dragStart, setDragStart] = useState<{ x: number; y: number } | null>(null); + const [selectedAspectRatio, setSelectedAspectRatio] = useState(null); // 选中的比例,null表示自定义 const resizeCanvasRef = useRef(null); const resizeContainerRef = useRef(null); + // 比例选项定义 + const aspectRatios = [ + { label: "智能", value: "smart", ratio: null }, // 智能:根据原图比例 + { label: "21:9", value: "21:9", ratio: 21 / 9 }, + { label: "16:9", value: "16:9", ratio: 16 / 9 }, + { label: "3:2", value: "3:2", ratio: 3 / 2 }, + { label: "4:3", value: "4:3", ratio: 4 / 3 }, + { label: "1:1", value: "1:1", ratio: 1 / 1 }, + { label: "3:4", value: "3:4", ratio: 3 / 4 }, + { label: "2:3", value: "2:3", ratio: 2 / 3 }, + { label: "9:16", value: "9:16", ratio: 9 / 16 }, + ]; + + // 根据比例和宽度计算高度 + const calculateHeightFromWidth = (width: number, ratio: number | null) => { + if (ratio === null) { + // 智能模式:使用原图比例 + if (image) { + return Math.round(width * (image.height / image.width)); + } + return resizeCanvasHeight; // 如果没有原图,保持当前高度 + } + return Math.round(width / ratio); + }; + + // 处理宽度变化 + const handleWidthChange = (newWidth: number) => { + setResizeCanvasWidth(newWidth); + if (selectedAspectRatio) { + const ratioConfig = aspectRatios.find((r) => r.value === selectedAspectRatio); + if (ratioConfig) { + const newHeight = calculateHeightFromWidth(newWidth, ratioConfig.ratio); + setResizeCanvasHeight(newHeight); + } + } + }; + + // 处理高度变化(如果用户手动修改高度,取消比例锁定) + const handleHeightChange = (newHeight: number) => { + setResizeCanvasHeight(newHeight); + // 如果用户手动修改高度,取消比例锁定 + if (selectedAspectRatio) { + setSelectedAspectRatio(null); + } + }; + + // 处理比例选择 + const handleAspectRatioSelect = (value: string | null) => { + setSelectedAspectRatio(value); + if (value) { + const ratioConfig = aspectRatios.find((r) => r.value === value); + if (ratioConfig) { + const newHeight = calculateHeightFromWidth(resizeCanvasWidth, ratioConfig.ratio); + setResizeCanvasHeight(newHeight); + } + } + }; + // 确保在客户端渲染 useEffect(() => { setMounted(true); @@ -467,6 +526,7 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel }: ImageAnnotator // 初始化尺寸为原图尺寸 setResizeCanvasWidth(image.width); setResizeCanvasHeight(image.height); + setSelectedAspectRatio(null); // 重置比例选择 // 初始化图片位置为画布中心 setResizeImagePosition({ x: 0, y: 0 }); setResizeImageScale(1); @@ -687,7 +747,8 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel }: ImageAnnotator } setProcessedImageBase64(base64Data); setProcessType("resize"); - setIsResizeMode(false); + // 不退出尺寸调整模式,保持原图显示 + // setIsResizeMode(false); toast.success(`尺寸调整完成!图片已调整为 ${resizeCanvasWidth}x${resizeCanvasHeight} 像素,已保存到相册`); } else { @@ -969,89 +1030,127 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel }: ImageAnnotator {/* 工具选择栏 / 尺寸调整工具栏 */} {isResizeMode ? ( /* 尺寸调整模式下显示尺寸调整工具栏 */ -
+
+ {/* 比例选择 */}
- - setResizeCanvasWidth(Number.parseInt(e.target.value) || 1)} - className="w-24 h-8" - min={1} - max={10000} - /> - px + +
+ {aspectRatios.map((ratio) => ( + + ))} +
-
- - setResizeCanvasHeight(Number.parseInt(e.target.value) || 1)} - className="w-24 h-8" - min={1} - max={10000} - /> - px -
-
- - setResizeBackgroundColor(e.target.value)} - disabled={resizeBackgroundTransparent} - className="w-12 h-8 rounded border cursor-pointer disabled:opacity-50" - /> -
-
-
) : ( @@ -1125,7 +1224,7 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel }: ImageAnnotator )} {/* 画布区域 - 并排显示原图和处理后的图片 */} -
+
{isLoading ? ( /* 加载动画 */
@@ -1149,26 +1248,32 @@ export function ImageAnnotator({ imageUrl, onConfirm, onCancel }: ImageAnnotator /* 尺寸调整模式 - 左右对比布局 */ <> {/* 左侧:原图 */} -
-
原图
-
+
+
原图
+
{image && ( 原图 )}
{/* 右侧:尺寸调整预览画布 */} -
-
调整尺寸
+
+
调整尺寸