使用Framer Motion实现卡片揭示动画时退出抖动问题求助
解决Framer Motion卡片揭示动画退出抖动问题
你的问题核心在于同时使用top/right这类触发重排的属性和scale动画,以及过渡配置不统一导致退出时的抖动。下面是修复后的代码和关键优化点:
关键优化项
- 用
transform: translate()替代top/right:translate属于GPU加速属性,不会触发页面重排,从根本上解决抖动问题 - 统一过渡配置:确保进入、悬停、退出动画使用一致的缓动曲线和时长,避免状态切换时的突兀感
- 明确
exit状态配置:原来的代码未定义退出状态,导致Framer Motion无法正确处理退出过渡
修复后的完整代码
const PortfolioSection: FC = () => { const list = [ { title: "abc", url: "https://www.example.com", image: "https://images.unsplash.com/photo-1488972685288-c3fd157d7c7a?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1740&q=80" }, { title: "klm", url: "https://www.example.com", image: "https://images.unsplash.com/photo-1487958449943-2429e8be8625?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1740&q=80" }, { title: "ost", url: "https://www.example.com", image: "https://images.unsplash.com/photo-1449157291145-7efd050a4d0e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1740&q=80" }, { title: "xyz", url: "https://www.example.com", image: "https://images.unsplash.com/photo-1598818384697-62330d600309?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=687&q=80" } ]; // 用translate替代top/right,统一过渡配置 const imgMotion = { initial: { // 初始状态:无偏移,原尺寸 translateX: 0, translateY: 0, scale: 1 }, hover: { // 悬停时:向右下偏移25%,缩小到0.5倍 translateX: "25%", translateY: "25%", scale: 0.5, transition: { duration: 0.3, type: "tween", ease: "easeInOut" } }, exit: { // 退出状态和初始状态一致,过渡和悬停保持统一 translateX: 0, translateY: 0, scale: 1, transition: { duration: 0.3, type: "tween", ease: "easeInOut" } } }; return ( <HomePageSection> <Grid container rowSpacing={4} columnSpacing={2} justifyContent="center" sx={{ height: "100%" }} > {list.map((item, i) => ( <Grid key={i} size={{ md: 6, xs: 12 }} > <motion.div initial="initial" whileHover="hover" whileTap="hover" exit="exit" style={{ width: "100%", height: "30vh", position: "relative", border: "4px solid green", overflow: "hidden" // 加上overflow:hidden,避免图片超出容器 }} > <div style={{ height: "50%", display: "grid", placeContent: "center", textTransform: "uppercase", backgroundColor: "black", color: "white" }} > <Typography variant="h4"> {item.title} </Typography> </div> <motion.div variants={imgMotion} style={{ height: "100%", width: "100%", backgroundImage: `url(${item.image})`, backgroundSize: "cover", backgroundPosition: "center center", zIndex: 10, position: "absolute", top: 0, right: 0 // 固定初始位置,用transform控制偏移 }} /> <Link href={item.url} target="_blank" style={{ position: "absolute", bottom: 0, right: 0, height: "50%", width: "50%", display: "grid", placeContent: "center", backgroundColor: "black", zIndex: 20 // 确保链接在图片上方 }} > Read more </Link> </motion.div> </Grid> ))} </Grid> </HomePageSection> ); };
额外注意点
- 给父容器加上
overflow: hidden,避免图片动画时超出容器范围 - 给链接设置更高的
z-index,确保悬停时依然可以点击 - 如果使用纯CSS方案,同样要替换
top/right为transform: translate(),并确保过渡属性只包含transform,减少性能开销
内容的提问来源于stack exchange,提问作者user10033434
相关产品推荐
相关产品推荐

