Next.js에서 Embla Carousel 라이브러리를 사용하여 Carousel Slider 만들기

Lenny·2022년 10월 4일
2

Embla Carousel 라이브러리를 사용하여 다음과 같은 슬라이더를 만드는법을 공유해보려고한다.

Embla-Carousel -> https://www.embla-carousel.com/

설치

npm install embla-carousel-react --save

위 명령어로 패키지를 설치한다.

적용

패키지를 설치했으면 파일을 하나 만들고 다운받은 패키지를 import 한다.

import React, { ReactNode, useCallback, useEffect, useState } from "react";
import useEmblaCarousel, { EmblaOptionsType } from "embla-carousel-react";

useEmblaCarousel 은 Embla 캐러셀을 구현하기 위한 핵심 패키지라고 이해하면 되고,
EmblaOptionsType 패키지는 타입스크립트 사용자들을 위한 Embla 캐러셀 슬라이더의 옵션들이 정의된 타입이다.

전체 코드를 보면서 설명하도록 하겠다.

위 GIF를 구현한 코드는 다음과 같다.

import React, { ReactNode, useCallback, useEffect, useState } from "react";
import useEmblaCarousel, { EmblaOptionsType } from "embla-carousel-react";

type PropType = {
  options?: EmblaOptionsType;
  slides: ReactNode[];
};

export const EmblaCarousel = (props: PropType) => {
  const { options, slides } = props; // props로 가져온 옵션과 슬라이드 리스트
  const [emblaRef, embla] = useEmblaCarousel(options); // 슬라이더 구현에 필요한 요소들을 useEmblaCarousel 에서 가져온다.
  const [selectedIndex, setSelectedindex] = useState(0); // 현재 보여지는 인덱스를 설정
  const [scrollSnaps, setScrollSnaps] = useState<number[]>([]); // 스크롤 스냅 Point 를 설정할 때 사용할 state

  // 이 코드는 구현할 때 사용하지 않았다. 하지만 나중에 혹시 쓰일 수 있을 것 같아서 남겨뒀다.
  const scrollTo = useCallback(
    (index: number) => embla && embla.scrollTo(index),
    [embla]
  );

  // 현재 선택된 슬라이더의 순서(인덱스)를 저장을 위한 함수
  const onSelect = useCallback(() => {
    if (!embla) return;
    setSelectedindex(embla.selectedScrollSnap()); 
    // selectedScrollSnap:  선택한 스냅 Point의 인덱스를 가져온다.
  }, [embla, setSelectedindex]);

  useEffect(() => {
    if (!embla) return;
    onSelect();
    setScrollSnaps(embla.scrollSnapList());
    embla.on("select", onSelect);
  }, [embla, setScrollSnaps, onSelect]);

  return (
    <div className="w-full relative rounded-md ">
      <div className="overflow-hidden relative rounded-md" ref={emblaRef}>
        <div className="flex flex-col flex-wrap h-44 flex-none">
          {slides.map((slide, index) => (
            <div className="w-full h-44 relative mx-1" key={index}>
              {slide}
            </div>
          ))}
        </div>
        <div className="absolute right-2 bottom-2 bg-[#0e0e0e72] rounded-full">
          <div className="flex justify-evenly items-center text-xs w-9 font-semibold">
            <span className="text-white">{selectedIndex + 1}</span>
            <div className="w-[2.05px] h-[2.05px] rounded-full bg-[#ffffffb2]" />
            <span className="text-[#ffffffb2]">{slides.length}</span>
          </div>
        </div>
      </div>
    </div>
  );
};

export default EmblaCarousel;

아래는 EmblaCarousel을 호출한 부분의 코드이다.

        <div className="flex justify-center items-center w-full h-44 rounded-md font-thin text-xl my-3">
          <Carousel
            slides={[
              <Image
                key={0}
                layout="fill"
                src={`/images/대책위원회1.jpg`}
                className=" object-cover rounded-md"
                alt="Image"
              ></Image>,
              <Image
                key={1}
                src={`/images/대책위원회2.jpg`}
                layout="fill"
                className=" object-cover rounded-md"
                alt="Image"
              ></Image>,
              <Image
                key={2}
                src={`/images/대책위원회3.jpg`}
                layout="fill"
                className=" object-cover rounded-md"
                alt="Image"
              ></Image>,
            ]}
            options={{
              align: "start",
              loop: true,
              skipSnaps: false,
              inViewThreshold: 0.7,
            }}
          />
        </div>

props로 slides와 options가 들어가는데, slides에는 배열안에 이미지 코드들을 넣어주었고, options prop에는 Embla Slider에 적용할 옵션들을 명시해주었다.

설명이 많이 부족한데, ( 특히 ScrollSnap 관련된 설명 )

한번 직접 콘솔에 찍어보면 Snap Point가 어떤 느낌인지 바로 알 수 있을 것이다!

profile
🧑‍💻

0개의 댓글