(S)CSS

React + scss 무한 (슬라이드)롤링 애니메이션 만들기

Hyunsangs 2024. 4. 27. 17:19

사이드 프로젝트를 진행하면서 무한 슬라이딩 애니메이션을 구현할 일이 생겨서 하게 되었다.

라이브러리를 따로 사용하지 않고 useState 훅과 함께 같이 만들어보았다.

다른 사람 글을 보고 참고한 코드여서 나의 맞게만 살짝 수정만 해보았다.

⚡동작 방식

구현하기 전 구현에 대한 설명이 필요하다.

  1. 먼저 슬라이드 형태로 흘러가야할 요소들을 한줄로 세워준다.
  2. 똑같은 요소들을 하나 더 만들어준다.

전체코드

home.js 전체 코드

import '../../Styles/Home.scss'
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
const Home = () => {
    const navigate = useNavigate()
    const [animate, setAnimate] = useState(true);
    const onStop = () => {
        setAnimate(false);
        console.log("onstop")
    }
    const onRun = () => {
        setAnimate(true);
        console.log('onRun')
    }

    const buttonHandler = () => {
        navigate('/imgGet')
    }

    const images = [
        '../img/0.jpg',
        '../img/12.jpg',
        '../img/24.jpg',
        '../img/38.jpg',
        '../img/76.jpg',
    ];

    return (
        <div className='main_home_wrapper'>
            <h1>내가 원하는 헤어스타일을 해주는 미용실 찾기</h1>
            <div className="wrapper">
                <div className="slide_container">
                    <ul
                        className="slide_wrapper"
                        onMouseEnter={onStop}
                        onMouseLeave={onRun}
                    >
                        <div
                            className={"slide original".concat(
                                animate ? "" : " stop"
                            )}
                        >   {images.map((s,i) => (
                            <li key={i}>
                                <img src={s} alt='img' />
                            </li>
                            
                        ))}
                        
                        </div>
                        <div
                            className={"slide clone".concat(animate ? "" : " stop")}
                        >
                            {images.map((s,i) => (
                            <li key={i}>
                                <img src={s} alt='img' />
                            </li>
                            
                        ))}
                        </div>
                    </ul>
                </div>
            </div>
            <div className='explain_wrapper'>
                <div className='title'>
                    <h1>내가 원하는 머리 스타일의 사진을 넣고 미용실을 찾아보세요.</h1>
                </div>
                <button onClick={buttonHandler}>시작하기</button>
            </div>
        </div>
        
    );
}

export default Home;

home.scss 전체코드

.wrapper {
        z-index: 1;
        width: 70%;
        border-top: 1px solid white;
        border-bottom: 1px solid white;
        padding: 40px;
        margin: 50px 0px;
        .slide_container {
            overflow: hidden;
    
            .slide_wrapper {
                display: flex;
                flex-wrap: nowrap;
            }
            .slide {
                display: flex;
                align-items: center;
                flex-wrap: nowrap;
                position: relative;
                padding: 50px 0;
    
                
                &.original {
                    animation: 30s linear infinite normal none running
                        infiniteAnimation1;
                }
                &.clone {
                    animation: 30s linear infinite infiniteAnimation2;
                }
                &.stop {
                    animation-play-state: paused;
                }
    
                li {
                    margin: 0 80px;
                    cursor: pointer;
                    z-index: 2;
                    transition: 0.3s;
                    transform: scale(1);
                    img {
                        width: 300px;
                        height: 350px;
                        object-fit: fill;
                    }
                    
                    &:hover {
                        transform: scale(0.98);
                        &::after {
                            content: "";
                            position: absolute;
                            top: 0;
                            left: 0;
                            bottom: 0;
                            right: 0;
                            width: 100%;
                            height: 100%;
                            background-color: rgba(0, 0, 0, 0.2);
                        }
                    }

                    
                }
            }
        }
    }
}

3. css 속성을 통해 한줄로 이어서 붙여준다. (부모속성에 flex와 nowrap처리를 통해 쉽게 구현이 가능하다.)

nowrap, flex 속성을 주게 되면 이런식으로 한 줄로 되어 짐.

 4.한줄이 된 슬라이드를 각기 다른 옵션으로 애니메이트를 처리한다.

 5.첫번째 원본 영역을 30초간 이동하면 그동안 빈 공백의 30초를 기다려야 하는데, 이때 복사 영역으로 똑같이 붙여서 30초간 이동시키고   무한으로 돌린다.

( 시간은 두 시간을 같게한다면 자기가 원하는 대로 바꿔도 상관 없다 )

6. 슬라이드 영역에 마우스를 올리면 animation-play-state의 값을 paused처리 하는 클래스를 토글 형태로 처리하면 된다.

결과