/** * 图片预览弹窗组件 * 支持多张图片左右切换、缩放、下载 */ import React, { useState } from 'react'; import { Modal, ModalOverlay, ModalContent, ModalBody, ModalCloseButton, Image, IconButton, HStack, Text, Box, } from '@chakra-ui/react'; import { ChevronLeft, ChevronRight, Download, ZoomIn, ZoomOut } from 'lucide-react'; import { motion, AnimatePresence } from 'framer-motion'; import { GLASS_BLUR } from '@/constants/glassConfig'; const MotionBox = motion(Box); const ImagePreviewModal = ({ isOpen, onClose, images = [], initialIndex = 0 }) => { const [currentIndex, setCurrentIndex] = useState(initialIndex); const [scale, setScale] = useState(1); // 切换到上一张 const handlePrevious = () => { setCurrentIndex((prev) => (prev - 1 + images.length) % images.length); setScale(1); // 重置缩放 }; // 切换到下一张 const handleNext = () => { setCurrentIndex((prev) => (prev + 1) % images.length); setScale(1); // 重置缩放 }; // 放大 const handleZoomIn = () => { setScale((prev) => Math.min(prev + 0.25, 3)); }; // 缩小 const handleZoomOut = () => { setScale((prev) => Math.max(prev - 0.25, 0.5)); }; // 下载图片 const handleDownload = () => { const link = document.createElement('a'); link.href = images[currentIndex]; link.download = `image-${currentIndex + 1}.jpg`; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; // 键盘快捷键 React.useEffect(() => { const handleKeyDown = (e) => { if (!isOpen) return; switch (e.key) { case 'ArrowLeft': handlePrevious(); break; case 'ArrowRight': handleNext(); break; case 'Escape': onClose(); break; case '+': case '=': handleZoomIn(); break; case '-': handleZoomOut(); break; default: break; } }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, [isOpen, currentIndex]); // 关闭时重置状态 const handleClose = () => { setScale(1); setCurrentIndex(initialIndex); onClose(); }; if (!images || images.length === 0) return null; return ( {/* 图片显示区域 */} {`图片 1 ? 'grab' : 'default'} userSelect="none" /> {/* 左右切换按钮(仅多张图片时显示) */} {images.length > 1 && ( <> } position="absolute" left="20px" top="50%" transform="translateY(-50%)" onClick={handlePrevious} size="lg" borderRadius="full" bg="blackAlpha.600" color="white" _hover={{ bg: 'blackAlpha.800', transform: 'translateY(-50%) scale(1.1)' }} _active={{ transform: 'translateY(-50%) scale(0.95)' }} aria-label="上一张" zIndex="2" /> } position="absolute" right="20px" top="50%" transform="translateY(-50%)" onClick={handleNext} size="lg" borderRadius="full" bg="blackAlpha.600" color="white" _hover={{ bg: 'blackAlpha.800', transform: 'translateY(-50%) scale(1.1)' }} _active={{ transform: 'translateY(-50%) scale(0.95)' }} aria-label="下一张" zIndex="2" /> )} {/* 底部工具栏 */} {/* 缩放控制 */} } size="sm" variant="ghost" color="white" onClick={handleZoomOut} isDisabled={scale <= 0.5} _hover={{ bg: 'whiteAlpha.200' }} aria-label="缩小" /> {Math.round(scale * 100)}% } size="sm" variant="ghost" color="white" onClick={handleZoomIn} isDisabled={scale >= 3} _hover={{ bg: 'whiteAlpha.200' }} aria-label="放大" /> {/* 下载按钮 */} } size="sm" variant="ghost" color="white" onClick={handleDownload} _hover={{ bg: 'whiteAlpha.200' }} aria-label="下载图片" /> {/* 图片计数(仅多张图片时显示) */} {images.length > 1 && ( {currentIndex + 1} / {images.length} )} {/* 快捷键提示 */} 快捷键: ← → 切换 | + - 缩放 | ESC 关闭 ); }; export default ImagePreviewModal;