(수정-1/19)이미지 추가, 이미지 슬라이더

개발공부·2022년 12월 28일
0

* 결과

1) 이미지 올리곤 난 후 이미지 3개 슬라이더

2) 이미지 1개인 경우(슬라이더)

3) 이미지 2개인 경우(슬라이더)

4) 이미지 4개인 경우(슬라이더)

* 1/19 기준 수정

* 무엇을 중점적으로 수정? - 1)

이미지 배치를 1개, 2개, 3개, 4개일 때 이미지 다르게 배치
참고한 유튜브 강의

* 이미지 배치 코드

const Test6 = () => {
  return (
    <>
      <h1>이미지 1개</h1>
      <div className="">
        <div className="bg-red-500 rounded-lg shadow-xl min-h-[50px]" />
      </div>
      <h1>이미지 2개</h1>
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-x-2 gap-y-3">
        <div className="bg-orange-500 rounded-lg shadow-xl min-h-[50px]" />
        <div className="bg-yellow-500 rounded-lg shadow-xl min-h-[50px]" />
      </div>
      <h1>이미지 3개</h1>
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-x-2 gap-y-3">
        <div className="bg-green-500 rounded-lg shadow-xl min-h-[50px] row-span-2" />
        <div className="bg-teal-500 rounded-lg shadow-xl min-h-[50px]" />
        <div className="bg-blue-500 rounded-lg shadow-xl min-h-[50px]" />
      </div>
      <h1>이미지 4개</h1>
      <div className="grid grid-cols-1 sm:grid-cols-2 gap-x-2 gap-y-3">
        <div className="bg-indigo-500 rounded-lg shadow-xl min-h-[50px]" />
        <div className="bg-purple-500 rounded-lg shadow-xl min-h-[50px]" />
        <div className="bg-pink-500 rounded-lg shadow-xl min-h-[50px]" />
        <div className="bg-slate-500 rounded-lg shadow-xl min-h-[50px]" />
      </div>
    </>
  );
};

export default Test6;

* 무엇을 중점적으로 수정? - 2)

▶ 개별 이미지 선택할 때 해당 이미지가 보여지도록 함

이미지 클릭 후 onZoom을 통해 ImageZoomModal로 이동 시 이미지 이름(imgName)과 숫자(num) 전달

첫 번째 이미지 -> 숫자 0
두 번째 이미지 -> 숫자 1
세 번째 이미지 -> 숫자 2
네 번째 이미지 -> 숫자 3

[components/PostImages.js]

 const [showImg, setShowImg] = useState("");
  const [showNum, setShowNum] = useState(0);
  
 const onZoom = useCallback(
    (imgName, num) => () => {
      setShowNum(num);
      setShowImg(imgName);
      setShowImagesZoom(true);
    },
    []
  );

return (
 	<img src={`http://localhost:3005/${images[0]?.src}`}
            alt={images[0]?.src}
            className="rounded-lg shadow-xl min-h-[50px]"
            onClick={onZoom(images[0]?.src, 0)}
          />
          
          {showImagesZoom && (
          <ImagesZoomModal
            images={images}
            onClose={onClose}
            showImg={showImg} //이미지 이름
            showNum={showNum} //이미지 개별 숫자
          />
        )}
)

* 무엇을 중점적으로 수정? - 3)

▶ 해당 이미지 선택 시 왼쪽, 오른쪽 슬라이더 기능 되도록 함

처음 이미지 클릭 시 클릭한 이미지 보여줄 것
두 번째 즉 왼쪽(leftButton) 혹은 오른쪽 버튼(rightButton) 클릭 시 처음 이미지 보여지지 않고 전달 받은 images에서 보여줄 것

mainImage true면 첫 이미지 보여줌 false면 이미지 보이지 않음
hideImages true면 슬라이더 되는 이미지 보여줌 false면 이미지 보여지 않음

[components/ImagesZoomModal.js]

//props로 전달받은 값들
const ImagesZoomModal = ({ showNum, showImg, images, onClose }) => {
  const [open, setOpen] = useState(true);
  const [num, setNum] = useState(showNum); //전달받은 숫자
  const [mainImage, setMainImage] = useState(true);
  const [hideImages, setHideImages] = useState(false);

  const leftButton = () => {
    setMainImage(false);
    setHideImages(true);
    if (num >= 1) { //가장 왼쪽에 있을 때 더 이상 클릭 안 됨
      setNum(num - 1);
    }
  };

  const rightButton = () => {
    setMainImage(false);
    setHideImages(true);
    const imgLength = images.length - 1;

    if (num < imgLength) { //가장 오른쪽에 있을 때 더 이상 클릭 안 됨
      setNum(num + 1);
    }
  };

  return (
    <>
                       <section>
                            <div className="relative">
                              {mainImage ? (
                                <img
                                  className="h-full w-full rounded-lg object-cover"
                                  src={`http://localhost:3005/${showImg}`}
                                  alt={showImg}
                                />
                              ) : null}
                              <ul id="slider">
                                {hideImages
                                  ? images.map((v, i) => (
                                      <li
                                        name="slide"
                                        className={`h-full w-full rounded-lg relative ${
                                          num === i ? null : "hidden"
                                        }`}
                                        // className={`h-[50vh] relative`}
                                        key={v.id}
                                      >
                                        <img
                                          className="h-full w-full rounded-lg object-cover"
                                          src={`http://localhost:3005/${v.src}`}
                                          alt={v?.src}
                                        />
                                      </li>
                                    ))
                                  : null}
                              </ul>
                              {images.length === 1 ? null : (
                                <div className="absolute px-5 flex h-full w-full top-0 left-0">
                                  <div className="my-auto w-full flex justify-between">
                                    <button className="bg-white p-2 rounded-full bg-opacity-80 shadow-lg">
                                      <ChevronLeftIcon
                                        onClick={leftButton}
                                        className="w-5 h-5"
                                      />
                                    </button>
                                    <button className="bg-white p-2 rounded-full bg-opacity-80 shadow-lg">
                                      <ChevronRightIcon
                                        onClick={rightButton}
                                        className="w-5 h-5"
                                      />
                                    </button>
                                  </div>
                                </div>
                              )}
                            </div>
                          </section>
    </>
  );
};

export default ImagesZoomModal;

* 문제점들

* form 태그 reload 현상

form 태그 안에 button이 두 개 존재한 상황
-> form 태그에서 submit 담당하는 경우 type="submit", 다른 하나는 type="button"

 <button
              type="button"
              onClick={onClickImageUpload}
              className="ml-2 bg-gray-100"
            >
              이미지 추가
            </button>
          </div>
          <button
            type="submit"
            className="flex hover:bg-light-green hover:text-white hover:rounded-md"
          >
            <PencilIcon className="h-5 w-5 md:h-8 md:w-8 lg:h-8 lg:w-8" />
            <h3 className="mt-1 mr-2 font-bold hover:text-white">추가</h3>
          </button>

* 참고한 내용들

* 이미지 슬라이더

▶ flowbite의 js 파일을 다운 받아야 작동 가능
▶ 실제 이미지 슬라이더에 참고한 것 (유튜브 강의)

document is undefined 오류(react)

useRef를 통해 childElementCount 이용하기

document.getElementById 대신 useRef 이용
DOM 조작 시 useRef를 사용함(game부분을 useRef를 사용해 수정할 것)

숫자를 반복문으로 사용(map)

ul안에 있는 li 태그 useRef로 접근

useRef로 classList.remove

[useRef로 classList.remove, add]

//document 이용(JS)

 const sliderElement = document.getElementById("slider");
    const totalSlides = sliderElement.childElementCount;
    console.log("totalSlides", totalSlides); //3
    
//리액트에서 사용 원할 경우 해당 변수들을 useEffect 안에 넣을 것
useEffect(() => {
    const sliderElement = document.getElementById("slider");
    const totalSlides = sliderElement.childElementCount;
    console.log("totalSlides", totalSlides);
  }, []);
    
return (
 <ul id="slider" >
            <li>
              <img
                src="https://placeimg.com/1200/800/nature"
                alt=""
              />
              <div>
                <h2>
                  Some Big Heading 1
                </h2>
              </div>
            </li>
           <li>
              <img
                src="https://placeimg.com/1200/800/nature"
                alt=""
              />
              <div>
                <h2>
                  Some Big Heading 2
                </h2>
              </div>
            </li>
            <li>
              <img
                src="https://placeimg.com/1200/800/nature"
                alt=""
              />
              <div>
                <h2>
                  Some Big Heading 3
                </h2>
              </div>
            </li>
          </ul>
)
//useRef 이용
 const totalSlides = useRef(null);
 
 const innerElements = totalSlides.current.innerHTML;
    let count = (innerElements.match(/<li/g) || []).length; //li값이 몇 개 있는지
    console.log("count", count); //3
 
 return (
 <ul id="slider" ref={totalSlides}>
            <li>
              <img
                src="https://placeimg.com/1200/800/nature"
                alt=""
              />
              <div>
                <h2>
                  Some Big Heading 1
                </h2>
              </div>
            </li>
           <li>
              <img
                src="https://placeimg.com/1200/800/nature"
                alt=""
              />
              <div>
                <h2>
                  Some Big Heading 2
                </h2>
              </div>
            </li>
            <li>
              <img
                src="https://placeimg.com/1200/800/nature"
                alt=""
              />
              <div>
                <h2>
                  Some Big Heading 3
                </h2>
              </div>
            </li>
          </ul>
)

* 이미지 슬라이드(Carousel)

* 코드

import React, { useCallback, useEffect, useState, useRef } from "react";
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/24/outline";

const Test = () => {
  const [id, setId] = useState(1);
  const totalSlides = useRef(null);

  const leftButton = () => {
    if (currentSlideId > 1) {
      setId(id - 1);
    }
  };

  const rightButton = () => {
    const innerElements = totalSlides.current.innerHTML;
    let count = (innerElements.match(/<li/g) || []).length; //3

    if (currentSlideId < count) {
      setId(id + 1);
    }
  };

  return (
    <>
      {console.log("id 결과", id)}
      <section>
        <div className="relative">
          <ul id="slider" ref={totalSlides}>
            <li
              name="slide"
              className={`h-[50vh] relative ${id === 1 ? null : "hidden"}`}
            >
              <img
                className="h-full w-full object-cover"
                src="https://placeimg.com/1200/800/nature"
                alt=""
              />
              <div className="absolute  top-0 left-0 h-full w-full flex">
                <h2 className="text-4xl font-bold text-white my-auto w-full text-center text-center px-20">
                  Some Big Heading 1
                </h2>
              </div>
            </li>
            <li
              name="slide"
              className={`h-[50vh] relative ${id === 2 ? null : "hidden"}`}
            >
              <img
                className="h-full w-full object-cover"
                src="https://placeimg.com/1200/800/animals"
                alt=""
              />
              <div className="absolute  top-0 left-0 h-full w-full flex">
                <h2 className="text-4xl font-bold text-white my-auto w-full text-center text-center px-20">
                  Some Big Heading 2
                </h2>
              </div>
            </li>
            <li
              name="slide"
              className={`h-[50vh] relative ${id === 3 ? null : "hidden"}`}
            >
              <img
                className="h-full w-full object-cover"
                src="https://placeimg.com/1200/800/tech"
                alt=""
              />
              <div className="absolute  top-0 left-0 h-full w-full flex">
                <h2 className="text-4xl font-bold text-white my-auto w-full text-center text-center px-20">
                  Some Big Heading 3
                </h2>
              </div>
            </li>
          </ul>

          <div className="absolute px-5 flex h-full w-full top-0 left-0">
            <div className="my-auto w-full flex justify-between">
              <button className="bg-white p-2 rounded-full bg-opacity-80 shadow-lg">
                <ChevronLeftIcon onClick={leftButton} className="w-5 h-5" />
              </button>
              <button className="bg-white p-2 rounded-full bg-opacity-80 shadow-lg">
                <ChevronRightIcon onClick={rightButton} className="w-5 h-5" />
              </button>
            </div>
          </div>
        </div>
      </section>
    </>
  );
};

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

0개의 댓글