IT/React

[react] μŠ€ν¬λ‘€μ— 따라 λ‚˜νƒ€λ‚˜κ³  μ‚¬λΌμ§€λŠ” λ„€λΉ„κ²Œμ΄μ…˜ λ°” κ΅¬ν˜„ν•˜κΈ° (Navbar)

ITyranno 2024. 1. 15. 09:51
728x90
λ°˜μ‘ν˜•

 

 

 

 

 

 

ν”„λ‘œκ·Έλž˜λ° 세계λ₯Ό νƒκ΅¬ν•©μ‹œλ‹€.

 

 

 

 

 

 

μŠ€ν¬λ‘€μ— 따라 λ‚˜νƒ€λ‚˜κ³  μ‚¬λΌμ§€λŠ” λ„€λΉ„κ²Œμ΄μ…˜ λ°” κ΅¬ν˜„ν•˜κΈ°

 

 

 

이번 ν”„λ‘œμ νŠΈμ—μ„œ μŠ€ν¬λ‘€μ— 따라 λ‚˜νƒ€λ‚˜κ³  μ‚¬λΌμ§€λŠ” λ„€λΉ„κ²Œμ΄μ…˜ λ°”λ₯Ό κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.

 

μŠ€ν¬λ‘€μ„ 내릴 λ•ŒλŠ” μ‚¬λΌμ‘Œλ‹€κ°€, μŠ€ν¬λ‘€μ„ 올리면 λ‹€μ‹œ λ‚˜νƒ€λ‚©λ‹ˆλ‹€.

 

 

 

 

κ΅¬ν˜„ ν™”λ©΄

 

 

 

 

 

 

 

μž‘μ„± μ½”λ“œ

 

λ§ˆμ§€λ§‰ 슀크둀 μœ„μΉ˜λ₯Ό κΈ°μ–΅ν•˜μ—¬ λ„€λΉ„κ²Œμ΄μ…˜ λ°”μ˜ ν‘œμ‹œ μƒνƒœλ₯Ό λ³€κ²½ν•˜λŠ” μ½”λ“œμž…λ‹ˆλ‹€.

 

슀크둀이 μ•„λž˜λ‘œ μ§„ν–‰ 쀑이면 false, 슀크둀이 μœ„λ‘œ μ§„ν–‰ 쀑이면 true둜 μ„€μ •ν•˜μ—¬ λ°” μƒνƒœλ₯Ό λ³€κ²½ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

 

 

Nav.jsx

import { useEffect, useState } from 'react';
import style from './Nav.module.css'
import { Link } from 'react-router-dom';

function Nav() {
    // λ„€λΉ„κ²Œμ΄μ…˜ λ°” ν‘œμ‹œ μƒνƒœλ₯Ό κ΄€λ¦¬ν•˜λŠ” state
    const [showNav, setShowNav] = useState(true);
    // λ§ˆμ§€λ§‰ 슀크둀 μœ„μΉ˜λ₯Ό μ €μž₯ν•˜λŠ” state
    const [lastScrollY, setLastScrollY] = useState(0);

    useEffect(() => {
        // 슀크둀 이벀트λ₯Ό μ²˜λ¦¬ν•˜λŠ” ν•¨μˆ˜
        const handleScroll = () => {
            const currentScrollY = window.scrollY;
            // 슀크둀이 μ•„λž˜λ‘œ μ§„ν–‰λ˜μ—ˆλŠ”μ§€ 확인
            if (currentScrollY > lastScrollY) {
                setShowNav(false); // μŠ€ν¬λ‘€μ„ 내릴 λ•Œ λ„€λΉ„κ²Œμ΄μ…˜ λ°” 숨기기
            } else {
                setShowNav(true); // μŠ€ν¬λ‘€μ„ 올릴 λ•Œ λ„€λΉ„κ²Œμ΄μ…˜ λ°” ν‘œμ‹œ
            }
            // λ§ˆμ§€λ§‰ 슀크둀 μœ„μΉ˜ μ—…λ°μ΄νŠΈ
            setLastScrollY(currentScrollY);
        };

        // 슀크둀 이벀트 λ¦¬μŠ€λ„ˆ 등둝
        window.addEventListener('scroll', handleScroll);

        // 클린업 ν•¨μˆ˜μ—μ„œ 이벀트 λ¦¬μŠ€λ„ˆ 제거
        return () => window.removeEventListener('scroll', handleScroll);
    }, [lastScrollY]); // lastScrollYκ°€ 변경될 λ•Œλ§ˆλ‹€ useEffectκ°€ μ‹€ν–‰λ©λ‹ˆλ‹€.

    return (
        <div className={`${style.header} ${showNav ? '' : style.hideNav}`}>
            <Link className={style.Logo} to="/">
                <img src={`${process.env.PUBLIC_URL}/img/logo.svg`} alt="MDS Logo" className={style.logo} />
            </Link>
            <div className={style.navbar}>
                <Link className={style.navbarMenu} to={'/map'}>
                    <img src={`${process.env.PUBLIC_URL}/img/mountainpath.svg`} alt="λ“±μ‚° 정보 μ•„μ΄μ½˜" className={style.icon1} />λ“±μ‚° 정보
                </Link>
                <Link className={style.navbarMenu} to={'/review'}>
                    <img src={`${process.env.PUBLIC_URL}/img/flag.svg`} alt="λ“±μ‚° ν›„κΈ° μ•„μ΄μ½˜" className={style.icon2} />λ“±μ‚° ν›„κΈ°
                </Link>
                <Link className={style.navbarMenu} to={'/rec'}>
                    <img src={`${process.env.PUBLIC_URL}/img/mountainrec.svg`} alt="λ“±μ‚°λ‘œ μΆ”μ²œ μ•„μ΄μ½˜" className={style.icon1} />λ“±μ‚°λ‘œ μΆ”μ²œλ°›κΈ°
                </Link>
            </div>
        </div>
    )
}


export default Nav;

 

 

 

Nav.module.css

 

.hidenav μŠ€νƒ€μΌμ—μ„œ navbarλ₯Ό μˆ¨κΈ°λŠ” 효과λ₯Ό μ μš©ν•©λ‹ˆλ‹€.

.header {
    display: flex;
    align-items: center;
    background-color: rgba(179, 179, 179, 0.42);
    padding-left: 2rem;
    z-index: 1000;
    /* λ‹€λ₯Έ μš”μ†Œλ“€ μœ„μ— μ˜€λ„λ‘ z-index μ„€μ • */
    position: fixed;
    transition: transform 0.3s ease;
    /* transform 속성에 λŒ€ν•œ μ „ν™˜ 효과 */
}

.logo {
    width: 12rem;
    height: 5rem;
}

.icon1 {
    width: 3rem;
    height: 1.5rem;
}

.icon2 {
    width: 2rem;
    height: 1.1rem;
}

.navbar {
    justify-content: center;
    width: 100vw;
    text-align: center;
    font-size: 1.2rem;
}

.navbarMenu {
    margin: 5rem;
    text-decoration: none;
    color: rgb(0, 0, 0);
    transition: color 0.3s ease;
    /* 색상 변화에 μ• λ‹ˆλ©”μ΄μ…˜ 효과λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€ */
    position: relative;
    /* 가상 μš”μ†Œμ˜ 기쀀점 μ„€μ • */
    overflow: hidden;
    /* 밑쀄이 링크 μ˜μ—­ λ°”κΉ₯으둜 λ‚˜κ°€μ§€ μ•Šλ„λ‘ μ„€μ • */
}

.navbarMenu:hover {
    color: #3ca50f;
    /* 마우슀 μ˜€λ²„ μ‹œ κΈ€μž 색상을 λ³€κ²½ν•©λ‹ˆλ‹€ */
}

.navbarMenu::after {
    content: '';
    /* 가상 μš”μ†Œμ˜ λ‚΄μš©μ€ λΉ„μ›Œλ‘‘λ‹ˆλ‹€ */
    position: absolute;
    left: 0%;
    /* μ™Όμͺ½μ—μ„œ 50%의 μœ„μΉ˜μ—μ„œ μ‹œμž‘ */
    bottom: -0.5rem;
    /* 링크 λ°”λ‹₯μœΌλ‘œλΆ€ν„° -0.5rem μœ„μ— μœ„μΉ˜ */
    width: 0;
    /* 초기 λ„ˆλΉ„λŠ” 0으둜 μ„€μ •ν•˜μ—¬ 보이지 μ•Šκ²Œ ν•©λ‹ˆλ‹€ */
    height: 0.13rem;
    /* λ°‘μ€„μ˜ λ‘κ»˜ */
    background: rgba(0, 0, 0, 0.279);
    /* λ°‘μ€„μ˜ 색상 */
    transition: width 0.5s ease, left 0.5s ease;
    /* λ„ˆλΉ„μ™€ μœ„μΉ˜μ— λŒ€ν•œ μ „ν™˜ 효과 μ„€μ • */
}

.navbarMenu:hover::after,
.navbarMenu:focus::after {
    width: 100%;
    /* 마우슀λ₯Ό μ˜¬λ¦¬κ±°λ‚˜ 포컀슀 μ‹œ λ°‘μ€„μ˜ λ„ˆλΉ„λ₯Ό 100%둜 λ³€κ²½ */
    left: 0;
    /* μœ„μΉ˜λ₯Ό μ™Όμͺ½ 끝으둜 λ³€κ²½ */
}

/* Nav.module.css */
.hideNav {
    transform: translateY(-100%);
    /* λ„€λΉ„κ²Œμ΄μ…˜ λ°”λ₯Ό μœ„λ‘œ μˆ¨κΉλ‹ˆλ‹€ */
    transition: transform 0.3s ease;
    /* λΆ€λ“œλŸ¬μš΄ μ „ν™˜ 효과 */
}

 

 

 

 

μœ„μ™€ 같은 λ°©μ‹μœΌλ‘œ μŠ€ν¬λ‘€μ— 따라 사라지고 λ‚˜νƒ€λ‚˜λŠ” λ„€λΉ„κ²Œμ΄μ…˜ λ°”λ₯Ό κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

728x90
λ°˜μ‘ν˜•