如何让Framer Motion自定义光标跟随鼠标同时持续动画?
解决Framer Motion自定义光标同时实现跟随鼠标与持续动画的问题
问题原因
你之前的代码中,将鼠标位置动画(通过variants的default状态)和持续循环动画(单独的animate对象)分开配置,导致Framer Motion只能执行其中一组动画规则,最终光标停留在左上角无法跟随鼠标。
解决方案
将鼠标位置的动态更新与持续循环动画合并到同一个animate配置中,并为不同属性分别设置过渡规则,让Framer Motion同时处理两种动画逻辑。
修改后的完整代码
import React, { useState, useEffect } from "react"; import { motion } from "framer-motion"; const CustomCursor = () => { // 初始位置设为窗口中心,避免初始状态在左上角 const [mousePosition, setMousePosition] = useState({ x: window.innerWidth / 2, y: window.innerHeight / 2, }); useEffect(() => { const updateMousePosition = (e) => { setMousePosition({ x: e.clientX, y: e.clientY, }); }; window.addEventListener("mousemove", updateMousePosition); return () => { window.removeEventListener("mousemove", updateMousePosition); }; }, []); const baseStyle = { transform: "translate(-50%, -50%)", width: "400px", height: "400px", filter: "blur(100px)", background: "linear-gradient(#43d9ad, #4d5bce)", opacity: 0.4, zIndex: 2, }; return ( <motion.div className={`fixed top-0 left-0 sm:hidden`} style={baseStyle} animate={{ // 跟随鼠标的位置(减去自身一半尺寸实现居中跟随) x: mousePosition.x - 200, y: mousePosition.y - 200, // 持续循环的动画属性 scale: [1, 2, 2, 1, 1], rotate: [0, 0, 270, 270, 0], borderRadius: ["20%", "20%", "50%", "50%", "20%"], }} transition={{ // 鼠标跟随用弹簧过渡,保证流畅性 x: { type: "spring", stiffness: 80, duration: 0.3 }, y: { type: "spring", stiffness: 80, duration: 0.3 }, // 循环动画用线性过渡,无限重复 scale: { duration: 4, repeat: Infinity, ease: "linear" }, rotate: { duration: 4, repeat: Infinity, ease: "linear" }, borderRadius: { duration: 4, repeat: Infinity, ease: "linear" }, }} ></motion.div> ); }; export default CustomCursor;
关键说明
- 合并动画配置:将鼠标位置的动态值和循环动画的keyframes都放在
animate对象中,Framer Motion会自动同步执行所有属性的动画。 - 分属性配置过渡:针对鼠标位置(x/y)使用弹簧过渡保证跟随的平滑感,针对循环动画属性(scale/rotate/borderRadius)设置无限重复的线性过渡,互不干扰。
- 优化初始位置:将初始鼠标位置设为窗口中心,避免组件挂载时光标突然从左上角跳到鼠标位置的突兀感。
内容的提问来源于stack exchange,提问作者buzz
相关产品推荐
相关产品推荐

