Dettlaff
Dettlaff

Reputation: 210

How to use animation multiple times in framer motion

Just like in the title, I'm trying to animate my component multiple times when clicking a button. Currently, animation only runs once and then it doesn't work anymore, how could I possibly implement that

here is an example of what I'm trying to do:

const controls = useAnimation();

    const handleClick = (e) => {
        controls.start({
            rotate: "360deg",
        });
    };

return(
<motion.button onClick={handleClick}>Button</motion.button>
<motion.div className="someRect" animate={controls}></motion.div>
)

Upvotes: 2

Views: 2373

Answers (2)

Lucas Henrique
Lucas Henrique

Reputation: 21

I actually faced the same issue today, so decided to post here in case anyone wonders what to do.

With the new useAnimate hook, we can just change the rotate back to 0 once the animation ends.

import "./styles.css";
import { useAnimate } from "framer-motion";

export default function App() {
  const [scope, animate] = useAnimate();

  const handleRotate = () => {
    animate(
      scope.current,
      { rotate: 180 },
      {
        duration: 0.5,
        onComplete() {
          animate(scope.current, { rotate: 0 }, { duration: 0 });
        },
      }
    );
  };

  return (
    <div className="App">
      <button onClick={handleRotate}>Rotate square</button>
      <div ref={scope} className="square" />
    </div>
  );
}

Here's the Code Sandbox with the implementation.

Upvotes: 2

indyanin
indyanin

Reputation: 852

To be honest, I've never worked with useAnimation controls so I have no idea what's going on here and how to come around this obstacle using your approach, but you may achieve what you are after with something like this.

  <button onClick={() => setRotate((prevState) => prevState + 360)}>
    Button
  </button>
  <motion.div
    className="someRect"
    animate={{
      rotate: rotate,
      transition: { duration: 3 }
    }}
    style={{ width: "100px", height: "100px", background: "red" }}
  >
  </motion.div>

I know that this solution is not optimal as the state is growing and growing with each click to possibly very substantial size which may cause problems at some point.

Check my solution in this CodeSanbox

Hope maybe someone will come up with a much more elegant solution which I'd appreciate seeing too.

Upvotes: 4

Related Questions