Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: Framer Motion / onClick activate only the animation

I am trying to animate an image with Framer Motion:

utils/MonkeyPicture.js

import React from 'react';

const MonkeyPic = () => {

        return (
            <div>               
                  <img
                    transition={{ duration: 0.5 }}
                    animate={{ rotate: [0, -30, 0]}}
                    id='monkeyFace'
                    src='/images/Monkey.png' />
                               
            </div>);         
}
export default MonkeyPic; 

So I would need a function that only adds or activates the atributes: transition={{ duration: 0.5 }} animate={{ rotate: [0, -30, 0]}} When I click on a Button.

The picture is rendered the whole time, I just wish to rotate it when I click a button.

The onClick method is in the AddTodo.js container:

            <button id='addTodo' onClick={() => {
                monkeySound.play(); 
                setShowFistBump(true);
                setTimeout(() => { 
                    setShowFistBump(false);
                }, 1000);
like image 854
FilipZafran Avatar asked Dec 31 '22 21:12

FilipZafran


2 Answers

You could use variants, for example like that:

// At first you need to pass `rotate` prop to MonkeyPic component inside your AddTodo
// You can use existing showFistBump state for that

<MonkeyPic rotate={showFistBump} />

// ...

// Then switch animation variant depending on that `rotate` prop

const variants = {
  rotate: { rotate: [0, -30, 0], transition: { duration: 0.5 } },
  // You can do whatever you want here, if you just want it to stop completely use `rotate: 0`
  stop: { y: [0, -10, 0], transition: { repeat: Infinity, repeatDelay: 3 } }
};

const MonkeyPic = ({ rotate }) => {
  return (
    <div>
      <motion.img
        variants={variants}
        animate={rotate ? 'rotate' : 'stop'}
        id="monkeyFace"
        src="/images/Monkey.png"
      />
    </div>
  );
};

Codesandbox link: https://codesandbox.io/s/httpsstackoverflowcomquestions63864386-rd1xh?file=/src/utils/MonkeyPicture.js

like image 180
Danila Avatar answered Jan 05 '23 16:01

Danila


In React changing an element's key makes React treat it as an entirely new component.

While framer provides us three types of animation use cases

  1. Enter animation { when component renders }
  2. Exit animation { when component is about to leave the dom tree }
  3. Gesture based animation

However there is a lack of like, trigger animation which will help us play an animation when we like, but anyways we will use the key prop of the component we are interested in and will set it's value to a ref, then to trigger it, we will change the ref's value so each time the component is re rendered and the entry animation is played, the example convers the theory

import React, { useRef, useState } from "react";
import { motion } from "framer-motion";

function ShakingButton({
  children,
  className,
  onClick,
}: {
  onClick?: React.MouseEventHandler<HTMLDivElement>;
  children: React.ReactNode;
  className: string;
}) {
  
  const ref = useRef(0);
  return (
    <motion.div
      key={ref.current}
      animate={ref.current === 0 ? {} : {
        x : [0, 10,-10,0]
      }}
      transition={{
        type: "spring",
      }}
      onClick={(e) => {
        onClick && onClick(e);
        ref.current++;
      }}
      className={className}
    >
      {children}
    </motion.div>
  );
}

export default ShakingButton;
like image 30
Snehal singh Avatar answered Jan 05 '23 18:01

Snehal singh