728x90

다이나믹 한 이미지 배열 사이즈를 슬라이드로 만들기

서버에서 이미지 URL 이 담긴 배열을 data 로 받아 이미지 슬라이드로 만드는 예제 입니다.

슬라이드를 만들기 위해서는 3개의 div 태그가 필요합니다.

 

<div className="swiper-container-main non-scroll">
	<div className="swiper-inner">
    	<div className="item">

 

container main 이 전체를 감싸는 wrapper 이고 이미지 전체의 길이를 담당합니다.

wiper inner 태그는 하나의 이미지를 보여주는 구간 입니다.

 

.swiper-container-main {
	// width: 300vw; 동적으로 구현할 것임
  transition: transform 0.5s;
}

.swiper-inner {
  width: 100vw;
  display: flex;
}

.swiper-inner img {
  width: 100%;
}

.non-scroll {
  overflow: hidden;
}

 

css 는 다음과 같습니다.

전체를 감싸는 컨테이너에 width 옵션은 이미지 배열을 받아와 그 길이로 동적으로 구현할 것이기 때문에 적지 않았습니다.

 

swiper-inner 에서 display: flex 를 줘서 이미지 들을 가로로 길게 나열 한뒤 width 옵션을 100vw(뷰포트 100%) 꽉차게 만듭니다.

 

swiper inner 태그 안에 img 태그의 이미지를 100%로 꽉차게 만들고 non-scroll 의 클래스 이름이 담긴 태그의 가로 스크롤을 숨김 처리 했습니다.

 

const Templates = () => {
  const swiperRef = useRef<HTMLDivElement>(null);
  const [swiperCurrentPosition, setSwiperCurrentPosition] = useState(0);
  const [loop, setLoop] = useState<any>();
  
  const imageData = axios.get('~~~~'); // 데이터를 가져오는 부분 로직은 생략합니다.
  
  useEffect(() => {
    swiperRef.current.style.width = imageData?.data
      ? `${imageData.data.length}00vw`
      : '0';
  }, [imageData]);

  useEffect(() => {
    if (!imageData?.data) return;
    const swiperLoop = setTimeout(() => {
      setSwiperCurrentPosition(prev => {
        if (prev < imageData.data.length - 1) {
          return prev + 1;
        } else return 0;
      });
    }, 3000);

    setLoop(swiperLoop);
    return clearTimeout(loop);
  }, [
    imageData?.data,
    setSwiperCurrentPosition,
    swiperCurrentPosition,
  ]);

  useEffect(() => {
    swiperRef.current.style.transform =
      swiperCurrentPosition === 0
        ? `translate(000vw)`
        : `translate(-${swiperCurrentPosition}00vw`;
  }, [swiperCurrentPosition]);
  
  ...

 

 

하나 씩 살펴보겠습니다.

 

...
const swiperRef = useRef<HTMLDivElement>(null);
...

<div ref={swiperRef} className="swiper-container-main">

swiper 컨테이너에 접근하기 위해서 ref 를 만들고 주입합니다 이렇게 한 이유는 style 값을 핸들링 하기 위해서 입니다.

 

useEffect(() => {
    swiperRef.current.style.width = imageData?.data
      ? `${recommendResponse.data.length}00vw`
      : '0';
  }, [recommendResponse]);

 

imageData 의 데이터가 있으면 컨테이너 뷰포트 전체의 길이를 그 길이 만큼 잡고 없다면 0 으로 잡습니다.

 

const [swiperCurrentPosition, setSwiperCurrentPosition] = useState(0);
const [loop, setLoop] = useState<any>(null);

useEffect(() => {
    if (!imageData?.data) {
      clearTimeout(loop);
    } else {
      const swiperLoop = setTimeout(() => {
        setSwiperCurrentPosition(prev => {
          if (prev < imageData.data.length - 1) {
            return prev + 1;
          } else return 0;
        });
      }, 3000);
      setLoop(swiperLoop);
    }
    return clearTimeout(loop);
  }, [
    imageData?.data,
    setSwiperCurrentPosition,
    swiperCurrentPosition,
  ]);

 

스와이퍼의 현재 위치 상태값을 담을 변수와 setTimeout 을 clear 해주기 위해서 useState 로 두개의 상태 관리 변수를 선언 합니다.

imageData 의 data 가 없다면

Timeout 을 클리어 하고 데이터가 있다면 그길이만큼 3초에 한번씩 다음 포지션 으로 넘어가는 루프를 만듭니다.

 

 

<div className="non-scroll">
	<div ref={swiperRef} className="swiper-container-main">
    	<div className="swiper-inner">
        	{imageData?.data &&
                  imageData.data.map((item: imageDataInterface) => (
                    <SlideItem
                      key={item.htmlTemplateId}
                      imageURL={item.previewImagePath}
                      templateTitle={item.categoryName}
                      templateCategory={item.name}
                    />
                  ))}
         </div>
  </div>
</div>

 

 

 

이미지 슬라이드 가 완성되었습니다.

 

이것을 잘 활용하신다면 버튼으로 이미지 넘기기 마우스로 이미지 넘기기 등등.. 구현 하실수 있습니다.

728x90