TIL - 흐르는 이미지

정길웅·2024년 3월 8일

TIL

목록 보기
7/9

yeastudio의 과제

https://www.yeastudio.net/about를 참고해서 웹사이트를 제작하라는 명령을 받아 사이트를 조사해보았다. 이 사이트에서 난이도있어보이는 애니메이션은 크게 두 종류였다.

  1. 흐르는 이미지
  2. 카드 뒤집기

그리고 내가 임의로 하나 추가한다면 스크롤을 움직일 때 그림이 양옆으로 움직이는거? 그렇게 총 3개가 이번 프로젝트의 목표가 되었다. 카드 뒤집기는 이전에 만든 경험이 있어서 내일 다시 펼쳐보고 오늘은 흐르는 이미지를 연구해보았다.

swiperjs 고려함

가장 먼저 고민했던 것은 swiperjs를 활용하는 것이었다. 직관적으로 보기에 carousel 형식으로 이미지들이 움직이고 있었고 infinite로 구현해야 했기에 swiper를 생각하였으나 툭툭 끊기는 느낌이 있었고 결국 버리게 되었다.

원리

텍스트 무한 이동, 이미지 흐르기 등등 여러차례 검색해보았고 괜찮은 참고자료를 얻게 되었다.
구현 방식에 대해 설명을 하자면

  1. 슬라이드 요소를 원본 영역과 복사 영역으로 나누어 한줄로 세운다.
  2. 10초를 기준으로 원본 영역을 transform: translateX()를 활용하여 밀어낸다.
  3. 원본 영역이 밀어내는 동안 복사 영역은 원래 속도로 이동하며 자리를 채운다.

코드

리액트를 활용한 코드는 다음과 같다.

/** InfiniteSlide.tsx */
interface _props {
  imageData: StaticImageData[]
  className: string
  direction: 'left' | 'right'
}

const InfiniteSlide = (props: _props) => {
  const { imageData, className, direction } = props
  return (
    <div className="flex flex-nowrap overflow-hidden">
      <ul className={`animate-infinite-flow-original flex min-w-[100vw] flex-nowrap `}>
        {imageData.map((item, i) => {
          return (
            <li className={className} key={i}>
              <Image src={item} alt={`이미지_${i}`} />
            </li>
          )
        })}
      </ul>
      <ul className={`animate-infinite-flow-copied flex min-w-[100vw] flex-nowrap `}>
        {imageData.map((item, i) => {
          return (
            <li className={className} key={i}>
              <Image src={item} alt={`이미지_${i}`} />
            </li>
          )
        })}
      </ul>
    </div>
  )
}

tailwind.config.ts는 다음과 같다.

import type { Config } from 'tailwindcss'

const config: Config = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {
      keyframes: {
        'infinite-flow-original': {
          '0%': { transform: 'translateX(0%)' },
          '50%': { transform: 'translateX(-100%)' },
          '50.1%': { transform: 'translateX(100%)' },
          '100%': { transform: 'translateX(0%)' },
        },
        'infinite-flow-copied': {
          '0%': { transform: 'translateX(0%)' },
          '100%': { transform: 'translateX(-200%)' },
        },
        'infinite-flow-reverse-original': {
          '0%': { transform: 'translateX(0%)' },
          '50%': { transform: 'translateX(100%)' },
          '50.1%': { transform: 'translateX(-100%)' },
          '100%': { transform: 'translateX(0%)' },
        },
        'infinite-flow-reverse-copied': {
          '0%': { transform: 'translateX(0%)' },
          '100%': { transform: 'translateX(200%)' },
        },
      },
      animation: {
        'infinite-flow-original': 'infinite-flow-original 60s linear infinite',
        'infinite-flow-copied': 'infinite-flow-copied 60s linear infinite',
        'infinite-flow-reverse-original': 'infinite-flow-reverse-original 60s linear infinite',
        'infinite-flow-reverse-copied': 'infinite-flow-reverse-original 60s linear infinite',
      },
    },
  },
  plugins: [],
}
export default config

보면 infinite-flow-original은 50%를 넘을 때 바로 초기 위치 뒤쪽으로 이동하고 infinite-flow-reverse는 기존 속도로 쭉 진행하는 것을 볼 수 있다.

결과

참고자료

티스토리

profile
사람들과 소통하는 FE 개발자입니다

0개의 댓글