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.