newcohospitality.com

Enhancing User Interaction with Framer Motion: Drag and Scroll

Written on

Framer Motion provides an excellent library for incorporating animations seamlessly into React applications. This article will guide you through the initial steps of using Framer Motion.

Drag Functionality

With Framer Motion, it's possible to implement drag-and-drop functionality in your React app. Here's a simple example to get you started:

import React from "react";

import { motion } from "framer-motion";

export default function App() {

return (

<>

<motion.div

drag

dragConstraints={{

top: -50,

left: -50,

right: 50,

bottom: 50

}}

style={{ backgroundColor: "red", width: 100, height: 100 }}

/>

</>

);

}

The drag prop allows the div to be draggable in any direction, while the dragConstraints prop limits the draggable area.

Using MotionValues

MotionValues can be utilized to monitor the state and velocity of various animation values. Here's how you can implement this feature:

import React from "react";

import { motion, useMotionValue, useTransform } from "framer-motion";

export default function App() {

const x = useMotionValue(0);

const background = useTransform(

x,

[-100, 0, 100],

["#f4fc03", "#ced41c", "#d4bb1c"]

);

return (

<motion.div style={{ background }}>

<motion.div

drag="x"

dragConstraints={{ left: 0, right: 0 }}

style={{ x }}

>

<div x={x}>foo</div>

</motion.div>

</motion.div>

);

}

This code changes the background color as you drag the text "foo" across the screen. The useTransform hook is paired with useMotionValue to create a dynamic value that changes based on the drag position.

Viewport Scroll Tracking

Framer Motion also allows tracking of viewport scroll progress, enabling animations that respond to user scrolling. Here's an example:

import React, { useEffect, useState } from "react";

import {

motion,

useSpring,

useTransform,

useViewportScroll

} from "framer-motion";

export default function App() {

const [isComplete, setIsComplete] = useState(false);

const { scrollYProgress } = useViewportScroll();

const yRange = useTransform(scrollYProgress, [0, 0.9], [0, 1]);

const pathLength = useSpring(yRange, { stiffness: 400, damping: 90 });

useEffect(() => yRange.onChange((v) => setIsComplete(v >= 1)), [yRange]);

return (

<>

<svg

className="progress-icon"

viewBox="0 0 200 200"

style={{ position: "fixed", top: 0, left: 50 }}

>

<motion.path

fill="none"

strokeWidth="5"

stroke="green"

strokeDasharray="0 1"

d="M 0, 20 a 20, 20 0 1,0 40,0 a 20, 20 0 1,0 -40,0"

style={{

pathLength,

rotate: 90,

translateX: 5,

translateY: 5,

scaleX: -1

}}

/>

<motion.path

fill="none"

strokeWidth="5"

stroke="green"

d="M14,26 L 22,33 L 35,16"

initial={false}

strokeDasharray="0 1"

animate={{ pathLength: isComplete ? 1 : 0 }}

/>

</svg>

<div>

{Array(100)

.fill()

.map((_, i) => (

<p key={i}>{i}</p>

))}

</div>

</>

);

}

In this example, an SVG containing a circle and a checkmark is used. As you scroll down, the pathLength of the circle increases, and the checkmark only appears when scrolling reaches the bottom.

Conclusion

Framer Motion makes it easy to integrate drag-and-drop features and track scroll progress, enhancing user interaction in your React applications.