import React, { useState, useEffect } from 'react'; import { Modal, Spin } from 'antd'; import { CloseOutlined } from '@ant-design/icons'; import './ImageModal.css'; interface ImageModalProps { visible: boolean; imageUrl: string; onClose: () => void; } // 图片缓存 const imageCache = new Set(); const ImageModal: React.FC = ({ visible, imageUrl, onClose }) => { const [loading, setLoading] = useState(false); const [imageLoaded, setImageLoaded] = useState(false); const [imageError, setImageError] = useState(false); const [isMobile, setIsMobile] = useState(false); const [imageDimensions, setImageDimensions] = useState<{ width: number; height: number } | null>(null); // 检测是否为移动端 useEffect(() => { const checkMobile = () => { setIsMobile(window.innerWidth <= 768); }; checkMobile(); window.addEventListener('resize', checkMobile); return () => window.removeEventListener('resize', checkMobile); }, []); // 预加载图片 useEffect(() => { if (visible && imageUrl) { // 如果图片已缓存,直接显示 if (imageCache.has(imageUrl)) { setImageLoaded(true); setLoading(false); return; } setLoading(true); setImageLoaded(false); setImageError(false); const img = new Image(); img.onload = () => { imageCache.add(imageUrl); setImageDimensions({ width: img.naturalWidth, height: img.naturalHeight }); setImageLoaded(true); setLoading(false); }; img.onerror = () => { setImageError(true); setLoading(false); }; img.src = imageUrl; } }, [visible, imageUrl]); // 重置状态当弹窗关闭时 useEffect(() => { if (!visible) { setLoading(false); setImageLoaded(false); setImageError(false); setImageDimensions(null); } }, [visible]); // 计算移动端弹窗高度 const getMobileModalHeight = () => { if (imageLoaded && imageDimensions) { // 如果图片已加载,根据图片比例自适应高度 const availableHeight = window.innerHeight - 64; // 减去标题栏高度 const availableWidth = window.innerWidth; // 计算图片按宽度100%显示时的高度 const aspectRatio = imageDimensions.height / imageDimensions.width; const calculatedHeight = availableWidth * aspectRatio; // 确保高度不超过可用空间的90% const maxHeight = availableHeight * 0.9; const finalHeight = Math.min(calculatedHeight, maxHeight); return `${finalHeight}px`; } // 图片未加载时,使用默认高度(除标题栏外的33%) return 'calc((100vh - 64px) * 0.33)'; }; const modalStyle = isMobile ? { // 移动端居中显示,不设置top paddingBottom: 0, margin: 0, } : { // PC端不设置top,让centered属性处理居中 }; const modalBodyStyle = isMobile ? { padding: 0, height: getMobileModalHeight(), minHeight: 'calc((100vh - 64px) * 0.33)', // 最小高度为33% maxHeight: 'calc(100vh - 64px)', // 最大高度不超过可视区域 display: 'flex', alignItems: 'center', justifyContent: 'center', backgroundColor: '#000', } : { padding: 0, height: '66vh', display: 'flex', alignItems: 'center', justifyContent: 'center', backgroundColor: '#000', }; return ( {/* 自定义关闭按钮 */}
{ e.currentTarget.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; }} onMouseLeave={(e) => { e.currentTarget.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'; }} >
{/* 图片内容 */}
{loading && ( )} {imageError && (
📷
图片加载失败
)} {imageLoaded && !loading && !imageError && ( 预览图片 )}
); }; export default ImageModal;