Animations are a powerful tool to enhance user experience, and when it comes to creating animations in React, Framer Motion is a popular library of choice.
Previously, we looked at 5 simple animations that you can add to your site. In this post, we will have a look at 3 complex animations or effects that can be created using Framer Motion in React that will take your website to the next level.
1. Follow Mouse Effect
In this effect, a small element, such as a circle, follows the mouse as it moves. To achieve this effect, we first need to track the cursor's position every time it moves. We store the x and y values of the mouse position in a state variable. Then, we create an effect that runs a function on pointermove
.
To get the mouse position relative to the object that will follow the mouse, we will add a ref
to that element. In the pointermove
function, we use the window's clientX
and clientY properties as object parameters. Here's the effect in the code:
useEffect(() => { // check if DOM element referenced by ref has been mounted if (ref.current) { const handlePointerMove = ({ clientX, clientY }) => { const element = ref.current; // calculate x and y coordinates const x = clientX - element.offsetLeft - element.offsetWidth / 2; const y = clientY - element.offsetTop - element.offsetHeight / 2; // update state setCoordinates({ x, y }); }; window.addEventListener("pointermove", handlePointerMove); return () => window.removeEventListener("pointermove", handlePointerMove); } }, []);
Here, element
refers to the DOM element currently referenced by the ref object (the circle that will follow the mouse in our case). The x and y coordinates are calculated by subtracting offsetLeft
and offsetTop
from the horizontal and vertical coordinates of the pointer's position on the screen (clientX and clientY). Finally, we subtract half of the width and height of the element from the values calculated above to ensure that the pointer is positioned at the center of the circle.
Next, we create the circle using a motion.div
component, assigning it the ref object. The x and y values will be animated using values from the state and we will also add a spring transition to create a cool bounce effect.
The complete code and the demo can be seen below:
2. Draggable List
A common feature found in most lists such as to-do lists, saved item lists or simply custom tabs is the option to rearrange items through drag-and-drop functionality. Let's dive into how you can create draggable lists using Framer Motion in React.
For this effect, we will utilize the ReOrder.Group
component available in Framer Motion. The list will be wrapped by this component or you can directly map out list items within this component. A few cool props that are available for the ReOrder.Group
component:
as
: Determine whether you want the list to be ordered or unordered.axis
: Specify the orientation of the list. For instance, vertical for to-do lists and horizontal for tabs.values
: The array of values utilized as the source.onReorder(newOrder)
: This is a callback function that runs when items are dragged and reordered. Usually, thestateSetter
function is passed if the list items are stored in a state array.
Furthermore, there are a few useful props for the Reorder.Item
component. You can check them out in the official docs.
The basics are quite simple. To create a demo of a draggable list, the following code provides the basics:
export default function App() { const [listItems, setListItems] = useState(list); return ( <Reorder.Group axis="y" onReorder={setListItems} values={listItems}> {listItems.map((el) => ( <Reorder.Item key={el} value={el}> <span>{el}</span> </Reorder.Item> ))} </Reorder.Group> ); }
Here, we are mapping out a state array of list items. Each item is represented as a Reorder.Item
within the Reorder.Group
. The axis is vertical, while the default as prop is an unordered list. The demo can be seen below:
3. Parallax Effect
The parallax effect is a widely used technique used to create depth and dynamism by moving elements at different speeds as the user scrolls through a webpage. We can create this effect using only a couple of lines of code with Framer Motion. In our example, we will have some text over a full-screen image. The text will move at a different speed compared to the background.
To create this effect, we will first calculate the vertical scroll progress of the page relative to a reference point (the text in our case). Then we will utilise the useTransform
hook and map this value onto a range of [-60, 60], which represents the maximum and minimum displacement of the text along the y-axis. This transformed value is then applied as the y property in the text's style, creating the desired parallax effect.
function App() { const textRef = useRef(); const { scrollYProgress } = useScroll({ target: textRef }); const y = useTransform(scrollYProgress, [0, 1], [-60, 60]); return ( <div className="app"> <motion.div className="text" ref={textRef} style={{ y: y, x: "-50%" }}> <h2>Hello, World!</h2> <p>Framer motion parallax effects are super cool!</p> </motion.div> <img src="https://cdn.pixabay.com/photo/2012/08/27/14/19/mountains-55067_640.png" className="background-image" /> </div> ); }
The scrollYProgress
gives us a value from 0 to 1 depending on the percentage of the page scroll with reference to the textRef
.
The result will look somewhat like this:
Thanks for reading!