Full Page 스크롤 라이브러리를 직접 만들어보자..

준영·2023년 7월 6일
2

코드 지갑..

목록 보기
14/20

Full Page 스크롤 라이브러리를 직접 만들어보자..

코드 (개선 전)

import { useEffect, useRef } from "react";
export default function Home() {
    const scrollRef = useRef(null);
    useEffect(() => {
        const handleScroll = (e: React.WheelEvent) => {
            const scrollTop = scrollRef.current.scrollTop;
            const viewHeight = window.innerHeight;
            const deltaY = e.deltaY;
            console.log(scrollTop, viewHeight);
            if (scrollRef.current) {
                console.log(e);
                // down wheel event
                if (deltaY > 0) {
                    if (scrollTop < viewHeight) {
                        console.log("1page");
                        scrollRef.current.scrollTo({
                            top: viewHeight * 2,
                            behavior: "smooth",
                        });
                    } else if (scrollTop < viewHeight * 2) {
                        console.log("2page");
                        scrollRef.current.scrollTo({
                            top: viewHeight * 2,
                            behavior: "smooth",
                        });
                    }
                }
                // up wheel event
                if (deltaY < 0) {
                    if (scrollTop < viewHeight) {
                        console.log("1page");
                        scrollRef.current.scrollTo({
                            top: 0,
                            behavior: "smooth",
                        });
                    } else if (scrollTop < viewHeight * 2) {
                        console.log("2page");
                        scrollRef.current.scrollTo({
                            top: 0,
                            behavior: "smooth",
                        });
                    }
                }
            }
        };
        if (scrollRef.current) {
            scrollRef.current.addEventListener("wheel",
            handleScroll);
        }
        return () => {
            if (scrollRef.current) {
                scrollRef.current.removeEventListener("wheel",
                handleScroll);
            }
        };
    }, []);
    return (
        <FullPageScrollWrapper ref={scrollRef}>
            <FullPageElement style={{ background: "red" }}>1</FullPageElement>
            <FullPageElement style={{ background: "blue" }}>2</FullPageElement>
        </FullPageScrollWrapper>
    );
}

이렇게 만들고 보니, 실제 라이브러리 처럼 스크롤 섹션 요소만 넣어주면 개수의 상관없이 스크롤이 가능하게 만들어보고 싶은 욕심이 생겨서 위의 코드를 개선해봤다.

코드 (개선 후)

import { useEffect, useRef } from "react";
export default function Home() {
    const scrollRef = useRef(null);
    const pageSection = [
        <FullPageElement style={{ background: "red" }}>1</FullPageElement>,
        <FullPageElement style={{ background: "green" }}>2</FullPageElement>,
        <FullPageElement style={{ background: "blue" }}>3</FullPageElement>,
        <FullPageElement style={{ background: "black" }}>4</FullPageElement>,
    ];
    useEffect(() => {
        const handleScroll = (e: React.WheelEvent) => {
            const scrollTop = scrollRef.current.scrollTop;
            const viewHeight = window.innerHeight;
            const deltaY = e.deltaY;
            console.log(scrollTop, viewHeight);
            if (scrollRef.current) {
                // down wheel event
                if (deltaY > 0) {
                    for (let i = 0; i < pageSection.length; i++) {
                        if (
                            scrollTop >= viewHeight * i &&
                            scrollTop <= viewHeight * (i + 1)
                        ) {
                            scrollRef.current.scrollTo({
                                top: viewHeight * (i + 1),
                                behavior: "smooth",
                            });
                        }
                    }
                }
                // up wheel event
                if (deltaY < 0) {
                    for (let i = 0; i < pageSection.length; i++) {
                        if (
                            scrollTop >= viewHeight * i &&
                            scrollTop <= viewHeight * (i + 1)
                        ) {
                            scrollRef.current.scrollTo({
                                top: viewHeight * (i - 1),
                                behavior: "smooth",
                            });
                        }
                    }
                }
            }
        };
        // 이벤트 등록
        if (scrollRef.current) {
            scrollRef.current.addEventListener("wheel",
            handleScroll);
        }
        // 메모리 최적화를 위해 이벤트 삭제 (선택사항)
        return () => {
            if (scrollRef.current) {
                scrollRef.current.removeEventListener("wheel",
                handleScroll);
            }
        };
    }, []);
    return (
        <FullPageScrollWrapper ref={scrollRef}>
            {pageSection}
        </FullPageScrollWrapper>
    );
}

배열 형식의 pageSection에 원하는 스크롤 섹션의 HTML요소만 넣어주면 잘 작동하는 모습을 볼 수 있다.

결과 화면

profile
개인 이력, 포폴 관리 및 기술 블로그 사이트 👉 https://aimzero-web.vercel.app/

5개의 댓글

comment-user-thumbnail
2023년 8월 4일

안녕하세요. 저도 동일하게 적용해 보았는데, 이동이 되지 않네요.
혹시 FullPageElement, FullPageScrollWrapper 컴포넌트 설정은 어떻게 하셨는지 알 수 있을까요?

'scrollRef.current' is possibly 'null'.ts(18047) 오류가 발생해 useRef의 타입은 any로 지정했습니다.

3개의 답글