3 Advanced Framer Motion Effects in React
Tags: react, framer, webdev, animation
Published: 2024-03-04 03:47:31

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.

> Check out this [post on my blog] (https://salehmubashar.com/blog/3-advanced-famer-motion-effects-in-react) 

---

## 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:

```javascript
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:

{% codesandbox f6wfgf %}

## 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, the `stateSetter` 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](https://www.framer.com/motion/reorder/).

The basics are quite simple. To create a demo of a draggable list, the following code provides the basics:

```javascript
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:

{% codesandbox ry93jn %}

## 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.

```javascript
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 demo can be seen below:

{% codesandbox sj87r6 %}

---

Thank you for reading

Check out this [post on my blog](https://salehmubashar.com/blog/3-advanced-famer-motion-effects-in-react) too.