Reputation: 1106
I have a custom cursor component in my react app. And for the smooth transition inside viewport I'm using framer motion.
The div under the mouse has some custom styling and it is following the cursor without any issues. But I want that div to animate all the time such as rotate + change border radius or even change bg color also.
From framer motion docs I went through the keyframes
section and after applying the same instruction it does animate but stops following the cursor.
It just stays top left corner of the screen and do the animation. But I want it animate while following the cursor.
import React, { useState, useEffect } from "react";
import { motion } from "framer-motion";
const CustomCursor = () => {
const [mousePosition, setMousePosition] = useState({
x: 0,
y: 0,
});
useEffect(() => {
const updateMousePosition = (e) => {
setMousePosition({
x: e.clientX,
y: e.clientY,
});
};
window.addEventListener("mousemove", updateMousePosition);
return () => {
window.removeEventListener("mousemove", updateMousePosition);
};
}, []);
const style = {
transform: "translate(-50%, -50%)",
width: "400px",
height: "400px",
borderRadius: "50% 22% 40% 80%",
filter: " blur(100px)",
background: "rgb(255, 67, 75)",
background: "linear-gradient(#43d9ad, #4d5bce)",
opacity: 0.4,
zIndex: 2,
};
const variants = {
default: {
x: mousePosition.x - 200,
y: mousePosition.y - 200,
},
};
const animate = {
scale: [1, 2, 2, 1, 1],
rotate: [0, 0, 270, 270, 0],
borderRadius: ["20%", "20%", "50%", "50%", "20%"],
};
return (
<motion.div
className={`fixed top-0 left-0 sm:hidden`}
style={style}
variants={variants}
//tried setting animate={animate} but didn't work
animate="default"
transition={{
duration: 0.3,
ease: "linear",
repeat: 0,
type: "spring",
stiffness: 80,
}}
></motion.div>
);
};
export default CustomCursor;
So how do I achieve the animate + follow cursor action here?
Upvotes: 2
Views: 7506
Reputation: 7447
Assuming that the goal is to have the animated element follow cursor and at the same time show a loop animation, it seems that the animate
values could be added to variants
, instead of defining another animate
property.
Simple demo of below example: stackblitz (the blur
is turned lower temporarily in the example for better visibility of motion).
const variants = {
default: {
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%"],
},
};
The transition
on motion.div
could be used to specify the desired properties for each animation. The default
key in below example can be edited to control the loop animation of scale
, rotate
and borderRadius
, in this use case.
<motion.div
className={`fixed top-0 left-0`}
style={style}
variants={variants}
animate="default"
transition={{
x: {
duration: 0.3,
ease: "linear",
repeat: 0,
type: "spring",
stiffness: 80,
},
y: {
duration: 0.3,
ease: "linear",
repeat: 0,
type: "spring",
stiffness: 80,
},
default: {
duration: 2.5,
repeat: Infinity,
},
}}
></motion.div>
Upvotes: 3