본문 바로가기

개발공부/REACT

[React] 간단한 갤러리 기능, 이미지 미리보기 만들기

프로젝트에서 구현하려고 했던 부분

- 가장 첫 번째 이미지가 기본이미지로 오도록 하고, 사진을 클릭하면 해당 사진으로 넘어가도록 구현

- prev, next 버튼을 누르면 이미지를 이동


UI 만들기

import FestivalImage from "../assets/FestivalImage1.png"
import FestivalImage2 from "../assets/FestivalImage2.png"
import FestivalImage3 from "../assets/FestivalImage3.png"
 const images = [   /* 이미지 경로를 리스트로 저장 */
 
    {
      source: FestivalImage,
    },
    {
      source: FestivalImage2,

    },
    {
      source: FestivalImage3,

    },
  ];
  
  const ImageContent = () => {
    return (
      <ImageContentWrap>
        <FestivalMainImageWrap>
        <FestivalMainImage src={FestivalImage} alt="Festival Image"></FestivalMainImage>
        </FestivalMainImageWrap>
        {images.map((image, index) => (
          <PreviewImage
            key={index}
            src={image.source}
            alt={`Image ${index}`}
          />
        ))}
      </ImageContentWrap>
    );
  };

 

우선 이미지를 import해서, map을 이용해 이미지가 보이도록 구현했다.

 

const ImageContentWrap = styled.div `
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
`

const FestivalMainImage = styled.img `
  margin-top: 50px;
  border-radius: 30px;
`;

const FestivalMainImageWrap = styled.div`
  width: 100%;
  display: flex;
  justify-content: center;
  margin-bottom: 10px;
`

const PreviewImage = styled.img `
  width: 80px;
  height: 80px;
  object-fit: cover;
  margin-right: 10px; /*사진 크기에 맞게 잘라짐*/

`

 

styled-component 부분은 이렇게 디자인 했다.

 

 

UI가 완성된 부분


기능 추가 _ 사진 누르면 해당 사진으로 바뀌는 기능

 const ImageContent = () => {

    const [selectedImage, setSelectedImage] = useState(images[0]);

    const onclickImage = (image) => {
      setSelectedImage(image);
    };
    return (
      <ImageContentWrap>
        <FestivalMainImageWrap>
        <FestivalMainImage src={selectedImage.source} alt="Festival Image"></FestivalMainImage>
        </FestivalMainImageWrap>
        {images.map((image, index) => (
          <PreviewImage
            key={index}
            src={image.source}
            alt={`Image ${index}`}
            onClick={() => onclickImage(image)}
          />
        ))}
      </ImageContentWrap>
    );
  };

 

- selectedImage라는 상태 추가 -> 현재 선택된 이미지를 나타내는 상태 (기본값은 첫 번째 이미지)

- onClickImage라는 함수로 클릭되었을 때 함수가 실행되면서 상태가 변경되도록 추가 

 


기능 추가 _  prev, next 버튼 

  const ImageContent = () => {
    const [selectedImageIndex, setSelectedImageIndex] = useState(0);

    const onClickImage = (index) => {
      setSelectedImageIndex(index);
    };
    const onNextImage = () => {  /* next버튼을 눌렀을 때 실행되는 함수 */
      setSelectedImageIndex((prevIndex) => (prevIndex + 1) % images.length);
    }; /* 이미지 Index가 하나 늘어나도록 구현 */
  
    const onPrevImage = () => { /* prev버튼을 눌렀을 때 실행되는 함수 */
      setSelectedImageIndex((prevIndex) =>
        prevIndex === 0 ? images.length - 1 : prevIndex - 1
      ); /* 이미지 Index가 하나 줄어들도록 구현 */
    };
  
    return (
      <ImageContentWrap>
        <FestivalMainImageWrap>
          <ButtonIcon xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40" fill="none" onClick={onPrevImage}>
            <path d="M25 30L15 20L25 10" stroke="#949494" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
          </ButtonIcon> /* prevButton 부분, onClick={onPrevImage}을 추가함 */
        <FestivalMainImage src={images[selectedImageIndex].source} alt="Festival Image"></FestivalMainImage>
          <ButtonIcon xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40" fill="none" onClick={onNextImage}>
            <path d="M15 30L25 20L15 10" stroke="#949494" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
          </ButtonIcon> /* nextButton 부분, onClick={onNextImage}을 추가함 */
        </FestivalMainImageWrap>
        {images.map((image, index) => (
          <PreviewImage
            key={index}
            src={image.source}
            alt={`Image ${index}`}
            onClick={() => onClickImage(image)}
          />
        ))}
      </ImageContentWrap>
    );
  };

 

const ImageContentWrap = styled.div `
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
`

const FestivalMainImage = styled.img `
  width: 800px;
  margin-top: 50px;
  border-radius: 30px;
`;

const FestivalMainImageWrap = styled.div`
  width: 100%;
  display: flex;
  justify-content: center;
  margin-bottom: 10px;
`

const PreviewImage = styled.img `
  width: 80px;
  height: 80px;
  object-fit: cover;
  margin-right: 10px; /*사진 크기에 맞게 잘라짐*/
  cursor: pointer;

`

const ButtonIcon = styled.svg `
  cursor: pointer;
  margin-top: 21%;
  margin-left: 30px;
  margin-right: 30px;
`

완성된 모습