react

react - 무한 롤링 슬라이드

카피새 2024. 3. 5. 10:30

참고해서 적용한 원글

https://myhappyman.tistory.com/312

 

React - 무한 롤링 슬라이드(배너) 구현하기

🎞️ 롤링 슬라이드 주식이나 뉴스같은 곳에서 한줄로 끊임없이 텍스트가 물처럼 한방향으로 흐르거나 요즘 트렌드의 스타일로 작성된 사이트들을 구경하다 보면 자주 접할 수 있는 스타일의

myhappyman.tistory.com

 

 

다른 분들의 코드도 한번 사용해보고 싶어 구글링을 많이 했다.

그 중 위의 블로그 글이 가장 트렌드에 맞기도 하고 내 프로젝트에 적용해보고 싶어서 가져왔다.

 

사용한 이벤트

onMouseEnter : 마우스 포인터가 요소 안으로 들어올 때(자식 포함) 발생, 요소 밖으로 나갔다 오지 않으면 계속 발생하지 않음

onMouseLeave : 마우스포인터가 요소 밖으로 이동 시 발생(자식요소로 이벤트 확산 X)

 

이벤트 활용법 보다는 css 활용법이 정말 중요하다 생각되는 구현 효과인 것 같다. 

원글에서도 css 레이아웃 개념, animation의 개념 @keyframe의 사용법을 익히는 것이 중요하다고 했다.

이번 애니메이션 효과를 제작하면서 css가 어려운 과목이구나 하는 것을 다시금 깨닫게 되었다.

 

구현 시작

- 컴포넌트

실제 코드가 담긴 컴포넌트 제작은 간단하다.

useState만을 사용하여 애니메이션의 시작, 정지를 관리할 수 있다.

다만 주의할 점은 원본 요소 + 복사 요소를 css를 통해(flex, nowrap처리) 한 줄로 만들어줘야 한다.

첫 번째 원본 영역을 10초간 이동 시 그간 빈 공백의 10초를 기다려야 한다. 이때 복사 영역으로 똑같이 붙여 10초간 이동 시키면 무한으로 돌아간다.

const Slider = ({teamImages}) => {

	// 애니메이션 제어 할 상태 변수
    const [animate, setAnimate] = useState(true);
    // 마우스가 슬라이더 진입 시 호출, false값으로 애니메이션 중지
    const onStop = () => setAnimate(false);
    // 마우스가 슬라이더 떠날 때 호출, true값으로 애니메이션 재시작
    const onRun = () => setAnimate(true);

    return (
        <div className="wrapper">
            <div className="slide_container">
                <ul
                    className="slide_wrapper"
                    onMouseEnter={onStop}
                    onMouseLeave={onRun}
                >
                    <div
                        className={"slide original" + (
                            animate ? "" : " stop"
                        )}
                    >
                        {teamImages.map((images, i) => (
                            <li
                                key={images.id}
                            >
                                <p className="item">
                                    <img src={`img/${images.img}.png`} alt={images.name} />
                                </p>
                            </li>
                        ))}
                    </div>
                    <div
                        className={"slide clone" + (animate ? "" : " stop")}
                    >
                        {teamImages.map((images, i) => (
                            <li
                                key={images.id}
                            >
                                <p className="item">
                                    <img src={`img/${images.img}.png`} alt={images.name} />
                                </p>
                            </li>
                        ))}
                    </div>
                </ul>
            </div>
        </div>
    );
};
export default Slider;

 

- CSS

간단하게 사용된 animatioin 속성을 정리하자면

 

linear : 일정한 속도로 진행

infinite : 애니메이션 무한 반복

normal : 정방향 재생

running : 애니메이션이 재생 중인 상태

paused : 애니메이션이 일시 정지 된 상태

 

각 속성들이 원래는

animation-속성종류: --; 이렇게 각각 쓰는 게 맞지만 본 코드처첨 animation 속성 하나로 줄여서 표현도 가능하다.

animation: 25s linear infinite normal none running infiniteAnimation1;

 

애니메이션 속성과 관련해 정리해놓은 사이트가 있어 참고용으로 링크 걸어놓을테니 한번씩 읽어보시길 추천한다.

https://apost.dev/882/

 

CSS 애니메이션(animation) 속성 이해하기

HTML 태그를 제외한 내용을 한글 존대말로 100자 이내로 요약하면 다음과 같습니다. 키프레임 애니메이션을 정의하고 애니메이션 속성을 사용하여 요소에 적용할 수 있습니다. "animation" 속성은 다

apost.dev

.wrapper{
    margin-bottom: 5%;
    overflow: hidden;
}
.wrapper .slide_container {
    width: 520%;
  }
  .wrapper .slide_container .slide_wrapper {
    display: flex;
    flex-wrap: nowrap;
  }
  .wrapper .slide_container .slide {
    display: flex;
    justify-content: space-between;
    flex-wrap: nowrap;
  }
  .wrapper .slide_container .slide.original {
    animation: 25s linear infinite normal none running infiniteAnimation1;
  }
  
  .wrapper .slide_container .slide.clone {
    animation: 25s linear infinite infiniteAnimation2;
  }
  
  .wrapper .slide_container .slide.stop {
    animation-play-state: paused;
  }
  
  .wrapper .slide_container .slide li {
    cursor: pointer;
    z-index: 2;
    transition: 0.3s;
    transform: scale(1);
    margin-left: 0.4%;
    margin-right: 0.4%;
  }
  .slide li .item img{
    width: 100%;
  }
  
  .wrapper .slide_container .slide li:hover {
    transform: scale(0.98);
  }
  
  .wrapper .slide_container .slide li:hover::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    width: 100%;
    height: 100%;
    border-radius: 20px;
    background-color: rgba(0, 0, 0, 0.2);
  }
  
  
  @keyframes infiniteAnimation1 {
    0% {
      transform: translateX(0%);
    }
    50% {
      transform: translateX(-100%);
    }
    50.1% {
      transform: translateX(100%);
    }
    100% {
      transform: translateX(0%);
    }
  }
  
  @keyframes infiniteAnimation2 {
    0% {
      transform: translateX(0%);
    }
    100% {
      transform: translateX(-200%);
    }
  }

 

 

완성본 짜잔

 

느낀 점

6개월간 css를 만졌지만, 정말 겉할기였구나라는 것을 느끼게 해준 animation 속성이었다. 간단하게 hover 사용 할 때만 애니메이션을 사용해서 그런 것 같다. 특히나 이번에 구현한 애니메이션은 다른 포트폴리오를 제작할 때도 매우 유용하게 사용이 될 것 같다는 생각이 든다.

css를 200% 활용하도록 노력하는 퍼블리셔 분들께 경의를 표하면서... 내가 얼마나 겉핥기식으로 공부했는 지 상기시킨 작업이었다.

애니메이션 효과를 제작하고 보니 클릭 시 이미지 확대, 상세 정보 모달창이 나와야 할 것 같아서 그것도 제작을 고려해봐야 할 것 같다.

국비과정이 이번주 목요일에 수료를 완료하는데 다른 분들의 포트폴리오를 보니 내 포트폴리오는 정말 별 거 없구나 싶었다. 하지만 이거 하나 완성했다고 이상한 자신감이 생기는 기분이다. 현재 포트폴리오에 자신감이 뚝뚝 떨어져 다른 프로젝트를 하나 진행해야 하나 싶었다. 그런데 이번 애니메이션 효과 적용을 계기로 내 포트폴리오에 조금은 생기가 도는 것 같아서 지금 포트폴리오를 보완하는 데 집중하기로 했다.

확실히 남들의 진행 속도를 주시하기 보다 내 것에 집중하는 것이 맞구나 싶은 작업이었다...