
마우스 커서에 스크롤 유도 표시를 따라다니도록 구현을 했다.

요런 식으로 마우스 움직이면 따라다닌다.
혹시 궁금하다면 👇👇
마우스 커서 스크롤 유도 표시
잘 따라다니는데 Navbar 위에 마우스가 있을 때는 커서가 pointer되서 겹쳐보인다...

이런식으로....
그래서 Navbar 위에서는 스크롤 유도 표시가 안보이게 해야겠다 생각!!
ref로 영역을 감지하고 해당 영역에 있으면 안보이도록 설정하자 !!
Context나 prop으로 nav DOM을 전달해야 되는데
nav에서 마우스 스크롤 유도 있는 DOM까지 prop drilling을 하기에는
너무 많은 계층을 거쳐야 하고 복잡하다...
그래서 zustand로 nav에 있는지를 전달하기로 결정 !!
// navStore.ts
import { create } from "zustand";
interface NavState {
navRect: DOMRect | null;
setNavRect: (react: DOMRect) => void;
}
export const useNavStore = create<NavState>((set) => ({
navRect: null,
setNavRect: (rect) => set({ navRect: rect }),
}));
// NavMenu.tsx
import { useRef, useEffect } from "react";
// store 가져오기
import { useNavStore } from "../_store/navStore";
export default function NavMenu() {
// ref 선언
const navRef = useRef<HTMLDivElement | null>(null);
const setNavRect = useNavStore((state) => state.setNavRect);
useEffect(() => {
if (navRef.current) {
const updateNavRect = () => {
// HTML 요소의 위치와 크기 정보 가져오기
const rect = navRef.current!.getBoundingClientRect();
// zustand에 저장
setNavRect(rect);
};
updateNavRect();
// 창 크기 바뀔 때마다 nav 위치 업데이트
window.addEventListener("resize", updateNavRect);
return () => {
// 컴포넌트가 사라질 때 이벤트 제거
window.removeEventListener("resize", updateNavRect);
};
}
}, []);
return (
<>
// nav영역 ref 연결
<ul className={styles.main} ref={navRef}>
<li className={styles.title}>
<Link href="/">DDIB</Link>
</li>
<li>
.....
</li>
</div>
</>
);
}
HTML 요소의 사각형 정보(=bounding box) 를 반환하는 메서드로 반환값은 DOMRect 객체
rect에 아래와 같은 속성들이 저장된다.
rect = {
top: number, // 화면 위쪽에서 요소까지의 거리 (px)
left: number, // 화면 왼쪽에서 요소까지의 거리 (px)
bottom: number, // top + height
right: number, // left + width
width: number, // 요소의 너비
height: number, // 요소의 높이
}
// MainArea.tsx
import { useState, useEffect } from "react";
import { useNavStore } from "@/app/_store/navStore";
export default function MainArea() {
// 저장해논 위치 zustand에서 가져오기
const navRect = useNavStore((state) => state.navRect);
// 현재 마우스 위치 저장
const [position, setPosition] = useState({ x: 0, y: 0 });
// nav위에 있는지 없는지 상태 저장
const [isOnNav, setIsOnNav] = useState(false);
useEffect(() => {
const handleMouseMove = (e: MouseEvent) => {
setPosition({ x: e.clientX, y: e.clientY });
if (navRect) {
// 현재 위치가 nav안에 있는지 체크
const isInside =
e.clientX >= navRect.left &&
e.clientX <= navRect.right &&
e.clientY >= navRect.top &&
e.clientY <= navRect.bottom;
// 영역안에 있으면 useState true로 바꿔준다
setIsOnNav(isInside);
// 영역안에 있으면 위치를 업데이트 하지 않는다
// 영역안에 없으면 위치 업데이트 해서 계속 따라다니게
if (!isInside) {
// 위치 업데이트
setPosition({ x: e.clientX, y: e.clientY });
}
}
};
document.addEventListener("mousemove", handleMouseMove);
return () => {
document.removeEventListener("mousemove", handleMouseMove);
};
}, [navRect]);
return (
<div className={styles.main}>
{data && (
<>
{data.todayNotOverProducts.length != 0 && (
<MainSlider todayList={data.todayNotOverProducts} onBg={handleBg} />
)}
<TodayItems todayList={data.todayProducts} bgColor={bgColor} />
</>
)}
<div
className={styles.scrollCursor}
// 스크롤 유도 표시 위치 지정
// nav안에 있으면 display : none으로 안보이게 설정
style={{
left: position.x,
top: position.y,
display: isOnNav ? "none" : "block",
}}
>
<div> Scroll</div>
</div>
</div>
);
}
이제 Navbar 위에 마우스를 hover하면

요로케ㅎㅎ
스크롤 유도 표시가 보이지 않고 커서 pointer만 나오는 것을 알 수 있다ㅎㅎㅎ