Search code examples
reactjsframer-motionreact-tsx

Framer-motion: Fire onTap() when click the other button


I have RotatingButton which is turning and changing scale when clicked.

(Rotating has to be slower so I used two motions and added duration to rotate.)

Button is adding +1 to state. ( addValue() )

    <div>
      <div>
        <motion.button
          onClick={addValue}
          animate={{ rotate: rotation }}
          transition={{ duration: 0.5, ease: 'easeIn' }}
        >
          <motion.div whileTap={{ scale: 0.8 }}>
            <RotatingButton />
          </motion.div>
        </motion.button>
      </div>
      <div>
        <button onClick={removeValue}>{text}</button>
      </div>
    </div>

But the problem is that I have second button which is removing -1 value from state ( removeValue() ) and it also has to turn and scale the RotatingButton.

Rotating is easy, I added dependency:

  const [rotation, setRotation] = useState<number>(0);

and setting rotation on each addValue() and removeValue().

  setRotation(rotation + 180);

but the problem is that I couldn't find the way to scale RotatingButton for 0.5 sec for example by triggering whileTap() on when removeValue() is triggered.

I've tried to make scale state and use useEffect nad trigger it when rotation is changing:

  useEffect(() => {
    setScale(0.8);
    setTimeout(() => {
      setScale(0);
    }, 300);
  }, [rotation]);

and I've also tried

const controls = useAnimationControls();

with controls.start, controls.mount etc.

To trigger it other way, with animation to change scale for 0.5 sec when changing the state, skipping whileTap.

I've tried onTapStart() too.

None of that worked. Please help me.


Solution

  • The way was to use sequence

    https://www.framer.com/motion/use-animation-controls/#sequence

      const controls = useAnimationControls();
      
    
      const sequence = async () => {
        await controls.start({ scale: 0.8, transition: { duration: 0.5 } });
        return await controls.start({ scale: 1, transition: { duration: 0.5 } });
      };
    

    and change whileTap() to animate={controls}

        <motion.button
          onClick={addValue}
          animate={{ rotate: rotation }}
          transition={{ duration: 0.5, ease: 'easeIn' }}
        >
          <motion.div animate={controls}>
            <RotatingButton />
          </motion.div>
        </motion.button>