Tạo hiệu ứng cuộn trang mượt mà khi lăn chuột với thư viện Framer Motion trong React
Demo sản phẩm
Link: https://thuanhmdev.github.io/react-framer-motion-smooth-when-wheel/
1. Giới thiệu
Trong thế giới phát triển web hiện đại, trải nghiệm người dùng là yếu tố quan trọng hàng đầu. Một trong những chi tiết nhỏ nhưng có thể tạo nên sự khác biệt lớn chính là hiệu ứng cuộn trang mượt mà. Thay vì cuộn trang theo cách thông thường, chúng ta có thể tạo ra một trải nghiệm cuộn mượt mà, tạo cảm giác cao cấp và chuyên nghiệp hơn cho website.
Trong bài viết này, chúng ta sẽ tìm hiểu cách tạo hiệu ứng cuộn trang mượt mà bằng cách sử dụng thư viện Framer Motion trong React. Framer Motion là một thư viện animation mạnh mẽ cho React, cung cấp các API đơn giản để tạo ra các hiệu ứng phức tạp.
2. Cài đặt
npm install framer-motion
3. Code mẫu và giải thích Code
Hãy xem xét code của component SmoothScroll:
import { motion, useScroll, useSpring, useTransform } from "framer-motion";
import React, { useLayoutEffect, useRef, useState } from "react";
export default function SmoothScroll({
children,
}: {
children: React.ReactNode;
}) {
const { scrollYProgress } = useScroll();
const smoothProgress = useSpring(scrollYProgress, {
mass: 0.1,
stiffness: 100,
damping: 30,
});
const [contentHeight, setContentHeight] = useState(0);
const contentRef = useRef<HTMLDivElement>(null);
const y = useTransform(
smoothProgress,
[0, 1],
contentHeight ? [0, -(contentHeight - window.innerHeight)] : [0, 0]
);
useLayoutEffect(() => {
const handleResize = () => {
if (contentRef.current) {
setContentHeight(contentRef.current.scrollHeight);
}
};
handleResize();
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
return (
<>
<div style={{ height: contentHeight }} />
<motion.div
className="scrollBody"
style={{
y,
position: "fixed",
top: 0,
left: 0,
right: 0,
overflowY: "hidden",
}}
ref={contentRef}
>
{children}
</motion.div>
</>
);
}
Hãy phân tích từng phần của code:
3.1. Import các hook cần thiết
import { motion, useScroll, useSpring, useTransform } from "framer-motion";
import React, { useLayoutEffect, useRef, useState } from "react";
3.2 Sử dụng các hook của Framer Motion
const { scrollYProgress } = useScroll();
const smoothProgress = useSpring(scrollYProgress, {
mass: 0.1,
stiffness: 100,
damping: 30,
});
useScroll() theo dõi tiến trình cuộn của trang.
useSpring() tạo ra một animation mượt mà dựa trên physics, với các tham số có thể điều chỉnh:
-
mass: Điều chỉnh "quán tính" của animation. Giá trị càng lớn, animation càng chậm khi bắt đầu và kết thúc.
-
stiffness: Điều chỉnh "độ đàn hồi". Giá trị càng cao, animation càng nhanh và "bật" mạnh hơn.
-
damping: Điều chỉnh "độ mượt". Kiểm soát mức độ animation sẽ dừng lại mượt mà.
3.3 Quản lý state và ref
const [contentHeight, setContentHeight] = useState(0);
const contentRef = useRef<HTMLDivElement>(null);
contentHeight lưu trữ chiều cao của nội dung.
contentRef tham chiếu đến phần tử DOM chứa nội dung.
3.4 Tính toán giá trị transform
const y = useTransform(
smoothProgress,
[0, 1],
contentHeight ? [0, -(contentHeight - window.innerHeight)] : [0, 0]
);
useTransform được sử dụng để chuyển đổi giá trị cuộn thành giá trị dịch chuyển Y. Nó kiểm tra contentHeight để tránh các giá trị không hợp lệ khi component mới được mount.
3.5. Xử lý sự kiện resize
useLayoutEffect(() => {
const handleResize = () => {
if (contentRef.current) {
setContentHeight(contentRef.current.scrollHeight);
}
};
handleResize();
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
Đoạn code này đảm bảo rằng contentHeight được cập nhật khi kích thước cửa sổ thay đổi.
3.6 Render component
return (
<>
<div style={{ height: contentHeight }} />
<motion.div
className="scrollBody"
style={{
y,
position: "fixed",
top: 0,
left: 0,
right: 0,
overflowY: "hidden",
}}
ref={contentRef}
>
{children}
</motion.div>
</>
);
Một div trống với chiều cao bằng contentHeight được tạo ra để giữ cho scrollbar của trình duyệt hoạt động bình thường.</br> motion.div chứa nội dung thực sự, với style position: fixed và transform y để tạo hiệu ứng cuộn mượt mà.</br>
3.7 Sử dụng SmoothScroll
Để sử dụng component này trong ứng dụng của bạn:
function App() {
return (
<SmoothScroll>
{/* Nội dung của trang web của bạn */}
<h1>Welcome to My Smooth Scrolling Website</h1>
<p>This content will scroll smoothly.</p>
{/* ... */}
</SmoothScroll>
);
}
Kết luận
Component SmoothScroll này sử dụng sức mạnh của Framer Motion để tạo ra hiệu ứng cuộn mượt mà, nâng cao trải nghiệm người dùng trên trang web của bạn. Bằng cách điều chỉnh các tham số của useSpring, bạn có thể tùy chỉnh cảm giác của animation để phù hợp với thiết kế của mình.
link source: https://github.com/thuanhmdev/react-framer-motion-smooth-when-wheel
All rights reserved