Creating An Animation Sequence Using Framer Motion
01 Mar 2022Framer Motion makes creating a sequence of animations easy.
In this example, we will create a React component that animates a circle in the center of three boxes.
This works by finding the bounding rectangle of each box. As we're using React a ref. Which is created like this
const box1Ref = useRef<HTMLDivElement>(null);
and used as follows
<div
className="w-20 h-20 border-2 border-purple-800 bg-purple-300"
ref="{box1Ref}"
></div>
With a reference to the element the calling getBoundingClientRect provides us with position and size properties.
const domRect: DOMRect | undefined = box1Ref.current?.getBoundingClientRect();
With this information we can to calculate the position where the circle to should move to.
const calculateCenter = (box, circle) => {
return {
top: box.y + box.height / 2 - (circle.y + circle.height / 2),
left: box.x + box.width / 2 - (circle.x + circle.width / 2),
};
};
Now we can create an animation sequence that moves the circle between the three boxes, which is easy as Framer Motion returns a promise for animations which is resolved upon when the animation is complete.
const circleRect = circleRef.current?.getBoundingClientRect();
const box1 = calculateCenter(
box1Ref.current?.getBoundingClientRect(),
circleRect,
);
const box2 = calculateCenter(
box2Ref.current?.getBoundingClientRect(),
circleRect,
);
const box3 = calculateCenter(
box3Ref.current?.getBoundingClientRect(),
circleRect,
);
await animation.start({
opacity: 1,
transition: { duration: 1 },
});
await animation.start({
top: box1.top,
left: box1.left,
transition: { duration: 1 },
});
await animation.start({
top: box2.top,
left: box2.left,
transition: { duration: 1 },
});
await animation.start({
top: box3.top,
left: box3.left,
transition: { duration: 1 },
});
The complete code for the example is available on CodePen
See the Pen Untitled by jagreehal (@jagreehal) on CodePen.