이미지 슬라이더, 이미지 스텝 비교(tailwindcss, typscript)

개발공부·2023년 4월 21일
0

React 공부하기

목록 보기
12/14
post-thumbnail

* 여러 이미지를 보여주는 방법 중 이미지 슬라이더와 이미지 스텝을 서로 비교하려고 함

* 결과

* 이미지 슬라이더

▶ 오른쪽, 왼쪽 방향키를 클릭 했을 때 변경
▶ 아래의 dot을 눌렀을 때 해당 이미지 이동

* 이미지 스텝

▶ 상단 바에 맞는 글자 클릭 했을 때 변경

* 정리 이유 및 문제점

  • 이미지 스텝의 경우 문제없이 작동했으나, 이미지 슬라이더의 경우 오류가 있었음
  • 이미지 슬라이더를 스텝처럼 각 이미지에 1, 2, 3 숫자 지정 후 이동하는 형식처럼 만들었으나 각 index를 정확히 찾지 못함

* [결론]

  • 이미지 스텝은 map을 사용해 보여줄 이미지를 찾아나가면 됨
  • 이미지 슬라이더는 전체 이미지[인덱스].이미지 주소를 통해 찾아나가면 됨

* 코드 정리

* 공통 코드(package.json과 위치 같음)

* [type.ts]

export interface IMainImages {
    id: number,
    name: string,
    image_path: string,
    description: string,
}

* [data.ts]

image_path는 public/images 안에 이미지 넣고 해당 주소 입력

export const mainImages: IMainImages[] = [
 	{
        id: 0,
        name: "강아지 1",
        image_path: "/images/dog1.jpg",
        description: "강아지 1 사진"
    },
    {
        id: 1,
        name: "고양이 1",
        image_path: "/images/cat1.jpg",
        description: "고양이 1 사진"
    },
    {
        id: 2,
        name: "강아지 2",
        image_path: "/images/dog2.jpg",
        description: "강아지 2 사진"
    },  
    {
        id: 3,
        name: "고양이 2",
        image_path: "/images/cat2.jpg",
        description: "고양이 2 사진"
    }
]

① 이미지 슬라이더

  • 이미지 형식을 map을 이용해 반복하면 정확한 이미지 위치를 찾지 못함
    ▶ 이미지 정보가 들어있는 mainImages 개별 위치를 currentIndex로 확인해 찾아야 함

오른쪽 버튼 moveRight 클릭 시 index + 1씩 증가 (0 -> 1 -> 2 -> 3)
왼쪽 버튼 moveLeft 클릭 시 index - 1씩 감소(3 -> 2 -> 1 -> 0)

[MainImgSlide.tsx] 일부 코드

showIndex는 0으로 고정
최소값(firstSlide)는 0, 최댓값(lastSlide)는 이미지 개수 - 1 (index는 0부터 세므로)

const moveLeft = () => {
    const firstSlide = showIndex === 0;
    const newIndex = firstSlide ? mainImages.length - 1 : showIndex - 1;
    setShowIndex(newIndex);
};


 const moveRight = () => {
    const lastSlide = showIndex === mainImages.length - 1;
    const newIndex = lastSlide ? 0 : showIndex + 1;
    console.log("right newIndex", newIndex)
    setShowIndex(newIndex);
  }

dotSlide는 사진 아래 점 버튼 눌렀을 때 해당 인덱스로 이동
-> map 함수를 이용해 index값을 찾아내고 받아 사진을 보여줌

const dotSlide = (slideIndex: number) => {
    setShowIndex(slideIndex)
}

[MainImgSlide.tsx] 전체 코드

import React, { useState } from 'react'
import { mainImages } from '@/data'
import { BsChevronCompactLeft, BsChevronCompactRight } from 'react-icons/bs';
import { RxDotFilled } from 'react-icons/rx';
import Image from 'next/legacy/image'

const MainImgSlide = () => {
const [showIndex, setShowIndex] = useState(0);


const moveLeft = () => {
    const firstSlide = showIndex === 0;
    const newIndex = firstSlide ? mainImages.length - 1 : showIndex - 1;
    setShowIndex(newIndex);
};


 const moveRight = () => {
    const lastSlide = showIndex === mainImages.length - 1;
    const newIndex = lastSlide ? 0 : showIndex + 1;
    setShowIndex(newIndex);
  }

const dotSlide = (slideIndex: number) => {
    setShowIndex(slideIndex)
}

  return (
    <>
    {console.log("showIndex", showIndex)}
      <div className='max-w-[600px] h-[350px] w-full m-auto relative grid place-items-center relative group'>
      <Image 
        className="w-full h-full bg-center bg-cover rounded-2xl" 
        src={mainImages[showIndex].image_path} 
        alt={mainImages[showIndex].image_path} 
        width={600}
        height={300}/>
        
    <div className='hidden group-hover:block absolute top-[45%] -translate-x-0 translate-y-[-50%] left-5 text-2xl rounded-full p-2 bg-black/20 text-white cursor-pointer'>
      <BsChevronCompactLeft onClick={moveLeft} size={30} />
    </div>

    <div className='hidden group-hover:block absolute top-[45%] -translate-x-0 translate-y-[-50%] right-5 text-2xl rounded-full p-2 bg-black/20 text-white cursor-pointer'>
      <BsChevronCompactRight onClick={moveRight} size={30} />
    </div>
    <div className='flex justify-center py-2 top-4'>
      {mainImages.map((slide, slideIndex) => (
        <div
          key={slideIndex}
          onClick={() => dotSlide(slideIndex)}
          className='text-2xl cursor-pointer'
        >
          <RxDotFilled />
        </div>
      ))}
    </div>
  </div>
    </>
  )
}

export default MainImgSlide

② 스텝

  • show, setShow을 이용해 보여줄 이미지 index값 표시
  • map을 이용해 MainImages에 이미지 전달

MainImageBar : 해당 글자 클릭 시 이미지 변경되도록 함, image={image} setShow={setShow} 전달

MainImages : setShow를 통해 전달된 show를 통해 이미지 변경, image={image} show={show} 전달

[MainItems.tsx] - 부모 컴포넌트

const MainItems = () => {
  const [show, setShow] = useState<number | null>(0); 

  return (
    <div className="flex grid items-center justify-center h-full gap-6 p-5">

	  <div className="grid w-full grid-cols-4 gap-4 p-3 space-x-2 text-sm font-medium text-center text-gray-500 bg-white border rounded-lg rounded-full shadow-sm border-gray-blue place-items-center ">
        {mainImages.map(image => (
            <MainImageBar image={image} setShow={setShow}/>
        ))}
    </div>
    
    <div className="grid w-full rounded-lg place-items-center">
        {mainImages.map(image => (
            <MainImages image={image} show={show} />
        ))}
    </div>
 )}

[MainImages.tsx] - 자식 컴포넌트 1

import React, { FunctionComponent } from 'react'
import Image from 'next/legacy/image'
import { IMainImages } from '@/type'

const MainImages:FunctionComponent<{image: IMainImages; 
  show:null|number;
  }> = ({image, show}) => {
  
  return (
   <>
    {show === image.id && (
    <div className="">
      <div className="">
          <p className="flex items-center font-bold">
            <span className="flex items-center justify-center w-5 h-5 mr-2 text-xs border rounded-full border-light-green shrink-0">
              {image.id + 1}
            </span>
            {image.name}
          </p> 
          <p>{image.description}</p>
      </div>
      <div className="flex justify-center text-gray-500">
            <Image 
            className="w-1/2 rounded-lg" 
            src={image.image_path} 
            alt={image.name} 
            width={500}
            height={300}/>
        </div>
    </div>
    )}
   </>
  )
}

export default MainImages

[MainImageBar.tsx] - 자식 컴포넌트 2

import { IMainImages } from '@/type';
import React, { FunctionComponent } from 'react'

const MainImageBar:FunctionComponent<{image: IMainImages; 
  setShow:(id:null | number) => void;}> = ({image, setShow}) => {

  return (
    <li className="flex items-center font-bold cursor-pointer" 
    onClick={() => setShow(image.id)}> 
    <span className="flex items-center justify-center w-5 h-5 mr-2 text-xs border rounded-full border-light-green shrink-0">
    {image.id}
    </span>
    {image.name}
  </li> 
  )
}

export default MainImageBar
profile
개발 블로그, 티스토리(https://ba-gotocode131.tistory.com/)로 갈아탐

0개의 댓글