I am using motion to animate a background color whenever the variable colorHex
changes, which works nicely. I would also like to scale up and back down each time the color changes. For this I've used scale: [1, 2, 1]
however because the value never changes, it only runs on the initial animation. How can I ensure it retriggers whenever colorHex
changes?
<motion.div
transition={{ duration: 0.3, delay: offset * 0.1, ease: "easeOut" }}
animate={{
backgroundColor: colorHex,
scale: [1, 2, 1],
}}
...
Note that the only work around I've found is to set the scale to a new (very slightly different) value when the color value changes.
First, you can trigger "manual" animations by using useAnimate
:
const [colorHex, setColorHex] = useState(getRandomColor());
const [scope, animate] = useAnimate();
const handleClick = () => {
setColorHex(getRandomColor());
animate(scope.current, { scale: [1, 2, 1] });
};
return (
<motion.div
ref={scope}
onClick={handleClick}
transition={{ duration: 0.3, delay: offset * 0.1, ease: "easeOut" }}
animate={{
backgroundColor: colorHex,
scale: [1, 2, 1],
}}
>
Hello World!
</motion.div>
)
Now that you have control on how to trigger the animation, you can just use React.useEffect
to listen for changes on your colorHex
:
export default function App() {
const [colorHex, setColorHex] = useState(getRandomColor());
const [scope, animate] = useAnimate();
useEffect(() => {
animate(scope.current, { scale: [1, 2, 1] });
}, [colorHex]);
const handleClick = () => {
setColorHex(getRandomColor());
};
return (
<motion.div
onClick={handleClick}
ref={scope}
transition={{ duration: 0.3, delay: offset * 0.1, ease: "easeOut" }}
animate={{
backgroundColor: colorHex,
scale: [1, 2, 1],
}}
>
Hello World!
</motion.div>
);
}
Here is a small repro with the full code.