video-flow-b/components/ui/ImageBlurTransition.tsx

69 lines
1.6 KiB
TypeScript

// Image3DFlipper.tsx
'use client';
import { motion, AnimatePresence } from 'framer-motion';
import { useEffect, useState } from 'react';
type ImageBlurTransitionProps = {
className?: string;
src: string;
alt?: string;
width?: number | string;
height?: number | string;
};
export default function ImageBlurTransition({ src, alt = '', width = 480, height = 300, className }: ImageBlurTransitionProps) {
const [current, setCurrent] = useState(src);
const [isFlipping, setIsFlipping] = useState(false);
useEffect(() => {
if (src !== current) {
setIsFlipping(true);
const timeout = setTimeout(() => {
setCurrent(src);
setIsFlipping(false);
}, 150); // 时长 = exit 动画时长
return () => clearTimeout(timeout);
}
}, [src, current]);
return (
<div
className={`relative rounded-xl ${className}`}
style={{
width,
height,
perspective: 1000, // 关键:提供 3D 深度
}}
>
<AnimatePresence mode="wait">
<motion.img
key={current}
src={current}
alt={alt}
className="absolute w-full h-auto object-cover rounded-xl"
initial={{
opacity: 0,
filter: 'blur(8px)',
scale: 1.02,
}}
animate={{
opacity: 1,
filter: 'blur(0px)',
scale: 1,
}}
exit={{
opacity: 0,
filter: 'blur(4px)',
scale: 0.98,
}}
transition={{
duration: 0.3,
ease: 'easeInOut',
}}
/>
</AnimatePresence>
</div>
);
}