무한 롤링 애니메이션

miin·2024년 11월 14일
0

Skill Collection [view]

목록 보기
18/19
import styled, { keyframes } from 'styled-components'

const test = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
const Rolling = () => {
    return (
        <div
            style={{
                marginTop: 30,
                overflow: 'hidden',
                display: 'flex',
                flexWrap: 'nowrap',
                width: '70%',
            }}
        >
            <RollingAnimation>
                {test.map((item, i) => (
                    <Item key={i}>{item}</Item>
                ))}
            </RollingAnimation>
            <RollingAnimation2>
                {test.map((item, i) => (
                    <Item key={i}>{item}</Item>
                ))}
            </RollingAnimation2>
        </div>
    )
}

export default Rolling

const infiniteAnimation1 = keyframes`
        0% {
        transform:translateX(0)
    }
    50% {
        transform:translateX(-100%)
    }
    50.1% {
        transform:translateX(100%)
    }
    100% {
        transform:translateX(0)
    }
`

const infiniteAnimation2 = keyframes`
    0% {
        transform:translateX(0%)
    }

    100% {
        transform:translateX(-200%)
    }
`
const Item = styled.div`
    width: 100px;
    height: 50px;
    background: gray;
    color: white;
    border-radius: 7px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: nowrap;
    margin-right: 10px;
`
const RollingAnimation = styled.div`
    display: flex;
    animation: 10s linear infinite normal none running ${infiniteAnimation1};
`
const RollingAnimation2 = styled.div`
    display: flex;
    animation: 10s linear infinite ${infiniteAnimation2};
`
  1. CSS 키프레임 애니메이션 정의

    @keyframes marquee {
    0% {
    transform: translateX(0%);
    }
    100% {
    transform: translateX(-100%);
    }
    }

  • 0%: 애니메이션 시작점, 원래 위치
    (translateX(0%))
  • 100%: 애니메이션 끝점, 왼쪽으로
    완전히 이동 (translateX(-100%))
  • translateX(-100%): 요소의 너비만큼
    왼쪽으로 이동
  1. 애니메이션 적용

    style={{animation: 'marquee 30s
    linear infinite'}}

  • marquee: 위에서 정의한 키프레임
    이름
  • 30s: 애니메이션 지속 시간 (30초)
  • linear: 일정한 속도로 애니메이션
    (가속/감속 없음)
  • infinite: 무한 반복
  1. HTML 구조

    {/* 부모: 넘치는 부분 숨김 */}
    {/* 첫 번째 그룹 */} SEIN WEB SEIN WEB ...
    {/* 두 번째 그룹 (복사본) */} SEIN WEB SEIN WEB ...
  2. 핵심 CSS 클래스들

  • overflow-hidden: 컨테이너 영역
    밖으로 나가는 텍스트 숨김
  • flex: 가로 배치
  • shrink-0: 요소가 줄어들지 않도록
    고정
  • whitespace-nowrap: 텍스트 줄바꿈
    방지
  1. 무한 롤링 원리

  2. 동일한 텍스트를 두 번 복사해서
    배치

  3. 첫 번째 그룹이 왼쪽으로 완전히
    사라질 때

  4. 두 번째 그룹이 정확히 첫 번째
    그룹의 원래 위치에 옴

  5. 애니메이션이 다시 시작되면서 끊김
    없는 무한 반복 구현

  6. 속도 조절 방법

    animation: marquee 15s linear
    infinite; / 더 빠름 /
    animation: marquee 60s linear
    infinite; / 더 느림 /

  7. 방향 변경 방법

    / 오른쪽으로 롤링 /
    @keyframes marquee-right {
    0% { transform: translateX(-100%);
    }
    100% { transform: translateX(0%);
    }
    }

중간에 끊기는 현상 발생

수정사항:
1. 구조 단순화: span 태그들을 제거하고 연속된 텍스트로 변경
2. min-w-full 추가: 각 텍스트 그룹이 최소한 화면 너비만큼 차지하도록
보장
3. 속도 조정: 30s → 15s로 변경 (더 부드러운 움직임)
4. 간격 통일:     로 일정한 간격 유지

끊김이 발생했던 이유:

  • 개별 span 태그들 사이의 미세한 간격

  • 첫 번째 그룹과 두 번째 그룹 사이의 타이밍 차이

  • mx-8 클래스로 인한 불균등한 마진

    해결 방법:

  • 연속된 텍스트로 구성해서 자연스러운 흐름 생성

  • min-w-full로 충분한 텍스트 길이 보장

  • 균등한 간격으로 시각적 일관성 확보

0개의 댓글