简体   繁体   中英

How can i make a child animation happen every time the parent animation is beginning using framer motion & react

I'm trying to make a squeezing bubble animation on repeat, using framer motion & react, but I cant make the squeeze animation happen every time the movement animation is beginning.

instead only the first time the animations run it works but after that only the movement animation repeats itself, if I try to repeat the squeeze animation it just gets out of order

import React from "react";
import styled from "styled-components";
import { motion } from "framer-motion";

const Bubble = () => {
  const shapeVariants = {
    hidden: {
      height: 450,
      width: 50,
    },
    visible: {
      height: 250,
      width: 250,
      transition: {
        type: "spring",
        bounce: 1,
        stiffness: 700,
        ease: "easeIn",
      },
    },
  };
  const MoveVariants = {
    hidden: {
      y: 1300,
    },
    visible: {
      y: -280,
      transition: {
        duration: 2,
        ease: "easeIn",
        repeat: Infinity,
      },
    },
  };

  return (
    <motion.div variants={MoveVariants} initial={"hidden"} animate={"visible"}>
      <RoundDiv
        onAnimationComplete={(definition) => console.log(definition)}
        variants={shapeVariants}
      />
    </motion.div>
  );
};

const RoundDiv = styled(motion.div)`
  height: 250px;
  width: 250px;
  background-color: #05386b;
  border-radius: 50%;
`;

export default Bubble;

The cascading animation in framer-motion is powered by the variant being propagated through the children.

You are running into this setback because you are only animating to the `visible variant once. Thus the variant propagation only happens once.

Potential Solutions

  1. Dumb solution: include a duration into the shapeVariant and make it also repeat then manually time your animation to where you need it. This isn't optimal because you probably want your bubble animation to be type spring?
 const shapeVariants = {
    hidden: {
      height: 450,
      width: 50,
    },
    visible: {
      height: 250,
      width: 250,
      transition: {
        type: "spring",
        bounce: 1,
        stiffness: 700,
        ease: "easeIn",
        duration: 2,
        repeat: Infinity
      },
    },
  };
  1. Alternatively you could control your animation with an effect that would use setTimeout or something to change the variant of the parent over and over to get the cascading effect

You just needed to add to your shapeVariants transition to get them to sync up.

import React from "react";
import styled from "styled-components";
import { motion } from "framer-motion";

const Bubble = () => {
    const shapeVariants = {
        hidden: {
            height: 450,
            width: 50,
        },
        visible: {
            height: 250,
            width: 250,
            transition: {
                type: "spring",
                bounce: 1,
                stiffness: 700,
                ease: "easeIn",
                duration: 2, /* new */
                repeat: Infinity, /* new */
            },
        },
    };
    const MoveVariants = {
        hidden: {
            y: 1300,
        },
        visible: {
            y: -280,
            transition: {
                duration: 2,
                ease: "easeIn",
                repeat: Infinity,
            },
        },
    };
    return (
        <motion.div
            variants={MoveVariants}
            initial={"hidden"}
            animate={"visible"}
        >
            <RoundDiv
                onAnimationComplete={(definition) => console.log(definition)}
                variants={shapeVariants}
            />
        </motion.div>
    );
};

const RoundDiv = styled(motion.div)`
    height: 250px;
    width: 250px;
    background-color: #05386b;
    border-radius: 50%;
`;

export default Bubble;

I would also recommend using originX and originY to manipulate the spring transition on the bubble otherwise it will animate the bounce based on the top left corner. I would use percentage values such as originX: "50%" but it depends on the effect you are looking for.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM