'use client'; import { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { XMarkIcon, PlayIcon } from '@heroicons/react/24/outline'; import SkinViewer from './SkinViewer'; interface SkinDetailModalProps { isOpen: boolean; onClose: () => void; texture: { id: number; name: string; url: string; type: 'SKIN' | 'CAPE'; is_slim?: boolean; description?: string; favorite_count?: number; download_count?: number; created_at?: string; uploader?: { username: string; }; } | null; isExternalPreview?: boolean; } export default function SkinDetailModal({ isOpen, onClose, texture, isExternalPreview = false }: SkinDetailModalProps) { const [currentAnimation, setCurrentAnimation] = useState<'idle' | 'walking' | 'running' | 'swimming'>('idle'); const [autoRotate, setAutoRotate] = useState(!isExternalPreview); const [rotation, setRotation] = useState(true); const [isMinimized, setIsMinimized] = useState(false); const [isPaused, setIsPaused] = useState(false); // 新增:动画暂停状态 // 重置状态当对话框关闭时 useEffect(() => { if (!isOpen) { setCurrentAnimation('idle'); setAutoRotate(!isExternalPreview); setRotation(true); setIsMinimized(false); setIsPaused(false); // 重置暂停状态 } }, [isOpen]); // 键盘事件处理 useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (!isOpen) return; switch (e.key) { case 'Escape': onClose(); break; case ' ': e.preventDefault(); // 空格键暂停/继续动画 setIsPaused(prev => !prev); break; case '1': setCurrentAnimation('idle'); break; case '2': setCurrentAnimation('walking'); break; case '3': setCurrentAnimation('running'); break; case '4': setCurrentAnimation('swimming'); break; case 'm': case 'M': setIsMinimized(prev => !prev); break; } }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, [isOpen, onClose]); // 动画控制函数 const handleAnimationChange = (animation: 'idle' | 'walking' | 'running' | 'swimming') => { setCurrentAnimation(animation); // 添加触觉反馈 if (navigator.vibrate) { navigator.vibrate(50); } }; const getModalVariants = () => ({ initial: { opacity: 0, scale: 0.7, rotateX: -15, y: 50 }, animate: { opacity: 1, scale: 1, rotateX: 0, y: 0, transition: { duration: 0.5, type: "spring" as const, stiffness: 100, damping: 15 } }, exit: { opacity: 0, scale: 0.7, rotateX: 15, y: 50, transition: { duration: 0.3 } }, minimized: { scale: 0.8, y: window.innerHeight - 200, x: window.innerWidth - 300, width: 280, height: 150, transition: { duration: 0.4 } } }); if (!texture) return null; return ( {isOpen && ( e.stopPropagation()} > {/* Header */}
{texture.name}
{texture.type === 'SKIN' ? '皮肤' : '披风'} {texture.is_slim && ( 细臂 )}
setIsMinimized(!isMinimized)} className="p-2 text-gray-500 hover:text-orange-500 dark:text-gray-400 dark:hover:text-orange-400 rounded-full hover:bg-orange-100 dark:hover:bg-orange-900/20 transition-all duration-200" whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.9 }} initial={{ opacity: 0, rotate: -180 }} animate={{ opacity: 1, rotate: 0 }} transition={{ delay: 0.6 }} title={isMinimized ? "最大化" : "最小化"} >
{!isMinimized && (
{/* 3D 预览区域 */}
{/* 控制面板 */} {/* 动画控制 */} 动画控制
{[ { key: 'idle', label: '静止', icon: null }, { key: 'walking', label: '步行', icon: null }, { key: 'running', label: '跑步', icon: null }, { key: 'swimming', label: '游泳', icon: null } ].map((anim, i) => ( ))}
{/* 信息面板 */}

皮肤信息

{texture.description && (

{texture.description}

)}
{texture.uploader && ( 上传者: {texture.uploader.username} )} {texture.created_at && ( 上传时间: {new Date(texture.created_at).toLocaleDateString()} )} 收藏数: {texture.favorite_count || 0} 下载数: {texture.download_count || 0}
{/* 快捷键提示 */}

快捷键

空格暂停/继续
1-4切换动画
M最小化
ESC关闭
)} {/* 最小化时的内容 */} {isMinimized && (

{texture.name}

)}
)}
); }