Home > Blockchain >  Framer motion - animation doesn't start after state change using controls
Framer motion - animation doesn't start after state change using controls

Time:12-16

I made custom dots for an image slider which in general work just fine. The dots trigger the image slider animation but I now have to pause the dots when the slides are hovered. My problem is that the first dot animates on first load then it does nothing until I hover over a slide it will continue and then stop again.

Without the controls they work perfect.

I'm not sure where the problem is in my component.

Here is a code sandbox that demonstrates the problem.

export const TimerDots = ({
  pauseDots,
  amount,
  duration,
  handleChange,
  activeIndex
}: {
  pauseDots?: boolean;
  amount: number;
  duration: number;
  handleChange: (e: any) => void;
  activeIndex: number;
}) => {
  const controls = useAnimation();

  const handleNextSlide = () => {
    handleChange((activeIndex  = 1));
  };

  const startAnimation = controls.start({
    width: SIZE * 3,
    transition: {
      duration: duration,
      type: "tween",
      ease: "easeOut"
    }
  });

  useEffect(() => {
    startAnimation;

    if (pauseDots) {
      controls.stop();
    }
  }, [pauseDots, activeIndex]);

  return (
    <DotContainer amount={amount}>
      {[...Array.from({ length: amount })].map((_, index) => {
        return (
          <Dot
            layout
            key={index}
            onClick={() => handleChange(index)}
            $active={activeIndex === index}
          >
            {activeIndex === index && (
              <Timer
                layout
                animate={controls}
                onAnimationComplete={handleNextSlide}
              />
            )}
          </Dot>
        );
      })}
    </DotContainer>
  );
};

CodePudding user response:

The problem comes from startAnimation and how its used in useEffect

When you do startAnimation in useEffect, you are not calling the function controls.start(..).

Try this:


const startAnimation = () => {
    controls.start({
      width: SIZE * 3,
      transition: {
        duration: duration,
        type: "tween",
        ease: "easeOut"
      }
    });
  };

  useEffect(() => {
    startAnimation();

    if (pauseDots) {
      controls.stop();
    }
  }, [pauseDots, activeIndex, controls]);

CodeSandbox.

  • Related