Home > Enterprise >  Why is my Framer Motion animation happening twice?
Why is my Framer Motion animation happening twice?

Time:01-14

I have an animation on a logo that I want to happen when the logo is being hovered over.

Here's the CodeSandbox Demo.

Current behavior: When you hover over the logo, the correct animation occurs. When you move off the logo, the middle path spins again.

Expected behavior: Animation occurs on hover, reverts back to contracted logo when mouse is no longer hovering

Any ideas?

Logo code:

import { motion, Variants } from "framer-motion";

interface LogoProps {
  hover?: boolean;
  width?: string;
  height?: string;
}

interface CustomVariants {
  [key: string]: Variants;
}

const Logo: React.FC<LogoProps> = (props: LogoProps) => {
  const customVariants: CustomVariants = {
    left: {
      rest: {
        x: 0
      },
      hover: {
        x: -20,
        transition: {
          repeat: 1,
          repeatType: "reverse",
          repeatDelay: 1
        }
      }
    },
    right: {
      rest: {
        x: 0
      },
      hover: {
        x: 20,
        transition: {
          repeat: 1,
          repeatType: "reverse",
          repeatDelay: 1
        }
      }
    },
    bottom: {
      rest: {
        y: 0
      },
      hover: {
        y: 20,
        transition: {
          repeat: 1,
          repeatType: "reverse",
          repeatDelay: 1
        }
      }
    },
    middle: {
      rest: {},
      hover: {
        rotate: -360 * 10,
        transition: {
          delay: 0.5
        }
      }
    }
  };

  return (
    <motion.svg
      width={props.width ?? 60}
      height={props.height ?? 60}
      viewBox="0 0 158 146"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      className="verifax-logo"
    >
      <motion.path
        id="side"
        d="M14.5017 66.3155C14.5327 75.092 14.8561 82.8129 15.1938 83.3718C15.4639 83.819 22.2984 87.9471 30.187 92.5369L44.6399 100.808L44.6607 85.4447C44.6485 76.9559 44.8577 69.0902 45.0151 67.811C45.3187 66.004 48.3905 64.16 60.19 58.5434C69.5292 53.9863 74.6938 50.9875 74.2886 50.3168C73.8834 49.6461 67.2327 45.5656 59.3629 41.2634L45.1125 33.3279L29.765 41.7966L14.4174 50.2652L14.5017 66.3155Z"
        fill="#6200EA"
        initial="hover"
        animate={props.hover ? "hover" : "rest"}
        variants={customVariants.left}
      />
      <motion.path
        className="side"
        d="M61.1382 25.1267C61.3405 25.4616 67.2779 28.8833 74.2679 32.7662C81.4415 36.6965 87.9483 40.5483 88.8361 41.2492C89.724 41.95 90.5114 49.4043 90.4749 58.0574C90.371 66.5989 90.6078 73.9104 90.8101 74.2453C91.0124 74.5802 97.8331 71.2631 106.077 66.7141L120.823 58.5772L120.855 42.4844C120.757 33.6081 120.501 26.0092 120.164 25.451C119.894 25.0045 113.136 20.9935 105.142 16.4739L90.593 8.27822L75.7307 16.4792C67.6029 20.9641 61.0033 24.9034 61.1382 25.1267Z"
        fill="#6200EA"
        animate={props.hover ? "hover" : "rest"}
        variants={customVariants.right}
      />
      <motion.path
        className="side"
        d="M59.6443 33.9735L59.5773 38.4802L70.0055 44.1985L80.5013 50.0285L63.9667 59.5989L47.4321 69.1693L47.5159 80.5954C47.6605 100.331 47.1504 98.974 52.497 96.0239C56.9137 93.5868 57.0599 93.0592 56.9503 84.9252C56.7873 69.52 55.3063 69.8902 74.0554 80.4036L90.9782 89.6898L104.926 81.9938L118.873 74.2978L114.437 71.8288L110.069 69.4716L99.1732 75.0366C93.178 78.1957 88.1425 80.3782 88.0075 80.1547C87.805 79.8194 87.6091 71.2861 87.503 61.3622L87.2685 43.0167L74.2791 35.8808C67.0983 31.9465 60.8736 28.8255 60.4087 29.082C59.9438 29.3386 59.5428 31.4967 59.6443 33.9735Z"
        fill="#6200EA"
        animate={props.hover ? "hover" : "rest"}
        variants={customVariants.middle}
      />
      <motion.path
        className="side"
        d="M59.2076 92.5587L59.4758 108.66L74.4152 116.963L89.4708 125.202L104.821 116.732L120.171 108.262L120.087 92.2088L120.07 76.2673L104.982 84.1454L89.8948 92.0235L75.2068 83.8795C67.0168 79.3053 60.1024 75.8161 59.6372 76.0728C59.2884 76.2653 59.0604 83.8447 59.2076 92.5587Z"
        fill="#6200EA"
        animate={props.hover ? "hover" : "rest"}
        variants={customVariants.bottom}
      />
    </motion.svg>
  );
};

export default Logo;

CodePudding user response:

Assuming that the goal is to remove the hover out effect for middle, since there is already a variant value rest for this element when not hovering, it seems that a transition of duration: 0 can be set with it so that the hover out effect is finished immediately.

Forked example with modification: codesandbox

middle: {
  rest: {
    rotate: 0,
    transition: {
      duration: 0,
    },
  },
  hover: {
    rotate: -360 * 10,
    transition: {
      delay: 0.5,
    },
  },
}
  • Related