如何用Framer Motion实现点击后闪烁的Next.js链接按钮?
实现Next.js链接按钮点击闪烁后跳转(仿Mac OS菜单项效果)
问题分析
你之前用AnimatePresence的思路不对,它是用来处理组件挂载/卸载时的动画,而这里需要的是点击触发的状态切换动画,且要等动画结束后再跳转页面。
解决方案
核心思路:
- 用Framer Motion的状态驱动动画,点击时触发闪烁效果
- 阻止Next.js
Link的默认跳转行为,手动在动画完成后执行页面跳转
完整代码实现
BlinkButton.js
import { useState } from 'react'; import { motion } from 'framer-motion'; export default function BlinkButton({ onClick, children, className }) { const [isBlinking, setIsBlinking] = useState(false); const handleClick = async (e) => { // 触发闪烁动画 setIsBlinking(true); // 等待动画完成(时长和动画配置对应,可按需调整) await new Promise(resolve => setTimeout(resolve, 200)); // 执行传入的跳转逻辑 onClick(e); }; return ( <motion.button className={className} onClick={handleClick} animate={isBlinking ? { opacity: 0 } : { opacity: 1 }} transition={{ duration: 0.1, repeat: 1, // 闪烁一次(透明→恢复) repeatType: "reverse" }} onAnimationComplete={() => setIsBlinking(false)} > {children} </motion.button> ); }
使用组件的页面/组件
import Link from 'next/link'; import BlinkButton from './BlinkButton'; export default function SomeOtherComponent({ href, icon, label }) { const handleNavigate = (e) => { // 阻止Link默认跳转,由按钮控制时机 e.preventDefault(); // 手动跳转页面,也可用Next.js的router.push(href) window.location.href = href; }; return ( <Link href={href} passHref> <BlinkButton onClick={handleNavigate} className="..."> {icon} <p>{label}</p> </BlinkButton> </Link> ); }
代码说明
- 动画逻辑:通过
isBlinking状态触发motion.button的透明度动画,repeat:1和repeatType:"reverse"实现“闪烁一次”的往复效果。 - 跳转控制:点击时先启动动画,用
setTimeout匹配动画时长等待结束,再执行跳转,确保动画完整展示。 - Link处理:添加
passHref属性传递链接地址,同时阻止默认跳转行为,避免打断动画流程。
自定义调整
- 可将透明度动画替换为背景色变化(比如
backgroundColor: ['#fff', '#e5e7eb', '#fff']),更贴近Mac菜单项的闪烁质感 - 修改
transition中的duration参数,控制动画快慢
内容的提问来源于stack exchange,提问作者mbaytas
相关产品推荐
相关产品推荐

