React를 사용한 반응형 캐러셀

Oluwafisayo Oluwatayo 2023년1월30일
  1. React Slick을 사용한 반응형 캐러셀
  2. React Hooks를 사용한 반응형 캐러셀
  3. React Material-UI를 사용한 반응형 캐러셀
  4. 결론
React를 사용한 반응형 캐러셀

React carousel은 항목을 슬라이드 형태로 표시할 수 있는 효과입니다. 이렇게 하면 보고 싶은 항목이 차례로 풀리므로 페이지를 위아래로 스크롤할 필요 없이 여러 항목을 쉽게 표시할 수 있습니다.

이 멋진 디자인은 전자 상거래 웹사이트에 이상적입니다. 한 번에 제품을 표시하는 좋은 방법입니다.

또한 포트폴리오를 만들고자 하는 사람에게 캐러셀 효과는 웹사이트 방문자가 스트레스 없이 제공되는 서비스를 볼 수 있도록 하는 데 탁월합니다.

React에서 이 슬라이딩 효과를 활용할 수 있는 다양한 방법이 있습니다. 화살표 버튼이 있는 회전 목마를 사용할 수 있으므로 사용자가 수동으로 앞으로 또는 뒤로 클릭하여 항목을 볼 수 있습니다.

루프처럼 항목이 처음부터 끝까지 자동으로 표시된 다음 다시 시작되는 자동으로 만들 수 있습니다.

따라서 앞으로 나아가서 React 프레임워크 내에서 이 함수를 호출하는 다양한 방법을 살펴보겠습니다.

React Slick을 사용한 반응형 캐러셀

이 예제는 react-slick 종속성을 활용하여 작동합니다. 새 프로젝트 폴더를 생성한 후 터미널 내부의 프로젝트 폴더로 이동하여 라이브러리를 설치합니다. npm install react-slick --save를 사용하여 설치합니다.

또한 React slick-carousel도 설치해야 합니다. 이렇게 하면 캐러셀의 CSS와 글꼴을 구성할 수 있습니다. npm install slick-carousel을 사용하여 이 종속성을 설치합니다.

그런 다음 우리는 두 개의 폴더를 만들 것입니다. 하나는 캐러셀용이고 다른 하나는 CSS 측면용입니다. Components 폴더를 생성하겠습니다. 그 안에 Slider.js를 만들 것입니다.

그런 다음 다른 폴더를 만듭니다. 우리는 이것을 css라고 부를 것입니다. 그리고 그 안에 App.scss 파일을 생성합니다.

그런 다음 Slider.js 파일로 이동하여 다음 코드를 입력합니다.

코드 조각(Slider.js):

import React from 'react';
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";


function ImageSlider() {
    let settings = {
        dots: true,
        infinite: true,
        speed: 500,
        slidesToShow: 3,
        slidesToScroll: 1,
        cssEase: "linear"
    }
    return (
        <Slider {...settings}>
            <div className="card-wrapper">
                <div className="card">
                    <div className="card-image">
                        <img src="images/1.jpg" />
                    </div>
                    <ul className="social-icons">
                        <li><a href="#"><i className="fa fa-facebook"></i></a></li>
                        <li><a href="#"><i className="fa fa-instagram"></i></a></li>
                        <li><a href="#"><i className="fa fa-twitter"></i></a></li>
                        <li><a href="#"><i className="fa fa-dribbble"></i></a></li>
                    </ul>
                    <div className="details">
                        <h2>BMW <span className="job-title">M5</span></h2>
                    </div>
                </div>
            </div>
            <div className="card-wrapper">
                <div className="card">
                    <div className="card-image">
                        <img src="images/2.png" />
                    </div>
                    <ul className="social-icons">
                        <li><a href="#"><i className="fa fa-facebook"></i></a></li>
                        <li><a href="#"><i className="fa fa-instagram"></i></a></li>
                        <li><a href="#"><i className="fa fa-twitter"></i></a></li>
                        <li><a href="#"><i className="fa fa-dribbble"></i></a></li>
                    </ul>
                    <div className="details">
                        <h2>Graphic <span className="job-title">Design</span></h2>
                    </div>
                </div>
            </div>
            <div className="card-wrapper">
                <div className="card">
                    <div className="card-image">
                        <img src="images/3.png" />
                    </div>
                    <ul className="social-icons">
                        <li><a href="#"><i className="fa fa-facebook"></i></a></li>
                        <li><a href="#"><i className="fa fa-instagram"></i></a></li>
                        <li><a href="#"><i className="fa fa-twitter"></i></a></li>
                        <li><a href="#"><i className="fa fa-dribbble"></i></a></li>
                    </ul>
                    <div className="details">
                        <h2>Embrace<span className="job-title">Your Darkness</span></h2>
                    </div>
                </div>
            </div>
            <div className="card-wrapper">
                <div className="card">
                    <div className="card-image">
                        <img src="images/4.jpg" />
                    </div>
                    <ul className="social-icons">
                        <li><a href="#"><i className="fa fa-facebook"></i></a></li>
                        <li><a href="#"><i className="fa fa-instagram"></i></a></li>
                        <li><a href="#"><i className="fa fa-twitter"></i></a></li>
                        <li><a href="#"><i className="fa fa-dribbble"></i></a></li>
                    </ul>
                    <div className="details">
                        <h2>ML <span className="job-title">Fashion</span></h2>
                    </div>
                </div>
            </div>
        </Slider>
    )
}

export default ImageSlider

사용하려는 항목의 데이터와 사진이 포함된 구성 요소를 만든 다음 이 모든 항목을 <Slider></Slider> 태그 안에 래핑합니다. 이것은 우리가 이전에 설치한 캐러셀 라이브러리입니다.

다음으로 App.js 폴더로 이동하여 다음 코드를 작성합니다.

코드 조각(App.js):

import ImageSlider from "./Components/Slider";
import "./css/App.css"
function App() {
  return (
    <div className="container mt-5 carousel">
      <h1 className="slider_title">React Image Carousel</h1>
      <ImageSlider />
    </div>
  );
}

export default App;

캐러셀은 웹 페이지를 위한 일종의 효과 디자인이기 때문에 CSS 측면은 설정에서 매우 중요한 부분입니다. 각 사진이 이동하는 방식과 전송하는 데 걸리는 시간을 제어하기 위해 많은 CSS를 수행할 것입니다.

코드 조각(App.scss):

* {
    margin: 0;
    padding: 0;
  }

  body {
    display: block;
    width: 100%;
    height: 100vh;
    overflow: hidden;
    font-family: "Raleway", sans-serif;
    position: relative;
    background: #333;
  }

  .slider_title {
    font-size: 5vw;
    color: tomato;
    text-transform: uppercase;
    text-align: center;
    margin-bottom: 2vw;
  }

  .card-wrapper {
    position: relative;
    width: 100%;
    padding: 0 10px;
    -webkit-box-sizing: border-box;
            box-sizing: border-box;
  }

  .card-wrapper:active, .card-wrapper:hover, .card-wrapper:focus {
    outline: none;
    border: none;
  }

  .card {
    width: 100%;
    height: 450px;
    border-radius: 16px;
    overflow: hidden;
    cursor: pointer;
    position: relative;
  }

  .card .card-image {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 2;
    background-color: #000;
    -webkit-transition: .5s;
    transition: .5s;
  }

  .card .card-image img {
    width: 100%;
    height: 100%;
    -o-object-fit: cover;
       object-fit: cover;
  }

  .card:hover img {
    opacity: .4;
    -webkit-transition: .5s;
    transition: .5s;
  }

  .card:hover .card-image {
    -webkit-transform: translateY(-100px);
            transform: translateY(-100px);
    -webkit-transition: all .9s;
    transition: all .9s;
  }

  .social-icons {
    position: absolute;
    top: 50%;
    left: 50%;
    -webkit-transform: translate(-50%, -50%);
            transform: translate(-50%, -50%);
    z-index: 3;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
  }

  .social-icons li {
    list-style: none;
  }

  .social-icons li a {
    position: relative;
    display: block;
    width: 50px;
    height: 50px;
    line-height: 50px;
    text-align: center;
    background: #fff;
    font-size: 23px;
    color: #333;
    font-weight: bold;
    margin: 0 6px;
    -webkit-transition: .4s;
    transition: .4s;
    -webkit-transform: translateY(200px);
            transform: translateY(200px);
    opacity: 0;
  }

  .card:hover .social-icons li a {
    -webkit-transform: translateY(0px);
            transform: translateY(0px);
    opacity: 1;
  }

  .social-icons li a:hover {
    background: #000;
    -webkit-transition: .2s;
    transition: .2s;
  }

  .social-icons li a:hover .fa {
    color: #fff;
  }

  .social-icons li a .fa {
    -webkit-transition: .8s;
    transition: .8s;
  }

  .social-icons li a .fa:hover {
    -webkit-transform: rotateY(360deg);
            transform: rotateY(360deg);
    color: #fff;
  }

  .card:hover li:nth-child(1) a {
    -webkit-transition-delay: .1s;
            transition-delay: .1s;
  }

  .card:hover li:nth-child(2) a {
    -webkit-transition-delay: .2s;
            transition-delay: .2s;
  }

  .card:hover li:nth-child(3) a {
    -webkit-transition-delay: .3s;
            transition-delay: .3s;
  }

  .card:hover li:nth-child(4) a {
    -webkit-transition-delay: .4s;
            transition-delay: .4s;
  }

  .details {
    position: absolute;
    bottom: 400px;
    left: 0;
    background: #fff;
    width: 100%;
    height: 120px;
    z-index: 1;
    padding: 10px;
    -webkit-transition: .6s;
    transition: .6s;
  }

  .details h2 {
    margin: 30px 0;
    padding: 0;
    text-align: center;
  }

  .details h2 .job-title {
    font-size: 16px;
    line-height: 2;
    color: #333;
    font-weight: 300;
    display: block;
  }

  .card:hover .details {
    bottom: 0;
  }

  .carousel .slick-dots {
    bottom: -2.5vw;
  }

  .carousel .slick-dots li button {
    width: 20px;
    height: 20px;
    border: 1px solid #fff;
    border-radius: 20px;
  }

  .carousel .slick-dots li button:before {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 10px;
    height: 10px;
    border-radius: 10px;
    content: "";
    text-align: center;
    opacity: .5;
    color: #000;
    background-color: #fff;
    -webkit-transform: translate(-50%, -50%);
            transform: translate(-50%, -50%);
    -webkit-transition: all .3s ease-in-out;
    transition: all .3s ease-in-out;
  }

  .carousel .slick-dots li.slick-active button, .carousel .slick-dots li:hover button {
    border-color: tomato;
  }

  .carousel .slick-dots li.slick-active button:before, .carousel .slick-dots li:hover button:before {
    background-color: tomato;
    opacity: 1;
  }

  .carousel .slick-prev, .carousel .slick-next {
    width: 50px;
    height: 50px;
    background-color: #fff;
  }

  .carousel .slick-prev:hover, .carousel .slick-prev:focus, .carousel .slick-next:hover, .carousel .slick-next:focus {
    color: #fff;
    outline:
   none;
    background: #fff;
  }

  .carousel .slick-prev:before, .carousel .slick-next:before {
    color: #000;
    font-family: "Raleway", sans-serif;
  }

  .carousel .slick-next {
    right: -55px;
  }

  .carousel .slick-prev {
    left: -55px;
  }

또한 CSS 내부에 그림 크기를 설정합니다. 또한 사진과 폰트에 추가되는 정보를 어떻게 표시할지 설정합니다.

출력:

React Slick을 사용한 반응형 캐러셀

React Hooks를 사용한 반응형 캐러셀

이 예제에서는 회전식 효과와 함께 발생하는 값 사이를 전환하는 데 도움이 되는 React의 useState 후크를 사용할 것입니다.

새로운 반응 프로젝트를 생성한 후 npm install react-icons를 사용하여 react-icons 라이브러리를 설치해야 합니다. 이 종속성은 이미지 사이를 이동하는 데 사용할 왼쪽 및 오른쪽 화살표 아이콘을 제공합니다.

그런 다음 프로젝트 폴더 내의 src 폴더로 이동하여 components라는 새 폴더를 만듭니다. 그 안에 SliderData.jsImageSlider라는 두 개의 파일을 만듭니다.

먼저 ImageSlider.js를 사용하여 코딩 측면을 진행합니다.

코드 조각(ImageSlider.js):

import React, { useState } from 'react';
import { SliderData } from './SliderData';
import { FaArrowAltCircleRight, FaArrowAltCircleLeft } from 'react-icons/fa';

const ImageSlider = ({ slides }) => {
  const [current, setCurrent] = useState(0);
  const length = slides.length;

  const nextSlide = () => {
    setCurrent(current === length - 1 ? 0 : current + 1);
  };

  const prevSlide = () => {
    setCurrent(current === 0 ? length - 1 : current - 1);
  };

  if (!Array.isArray(slides) || slides.length <= 0) {
    return null;
  }

  return (
    <section className='slider'>
      <FaArrowAltCircleLeft className='left-arrow' onClick={prevSlide} />
      <FaArrowAltCircleRight className='right-arrow' onClick={nextSlide} />
      {SliderData.map((slide, index) => {
        return (
          <div
            className={index === current ? 'slide active' : 'slide'}
            key={index}>
            {index === current && (
              <img src={slide.image} alt='travel image' className='image' />
            )}
          </div>
        );
      })}
    </section>
  );
};

export default ImageSlider;

useState 기능을 적용하여 nextSlide를 증가로 설정합니다. 즉, 다음 항목으로 이동하는 반면 prevSlide는 정반대입니다. 그런 다음 해당 화살표를 클릭할 때마다 이러한 기능을 활성화하기 위해 onClick 이벤트 리스너를 호출합니다.

계속해서 SliderData.js로 이동합니다. 여기에서 회전 목마 효과로 표시할 이미지 배열을 만듭니다.

코드 조각(SliderData.js):

export const SliderData = [
    {
        image:
            'https://images.unsplash.com/photo-1546768292-fb12f6c92568?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80'
    },
    {
        image:
            'https://images.unsplash.com/photo-1501446529957-6226bd447c46?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1489&q=80'
    },
    {
        image:
            'https://images.unsplash.com/photo-1483729558449-99ef09a8c325?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1350&q=80'
    },
    {
        image:
            'https://images.unsplash.com/photo-1475189778702-5ec9941484ae?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1351&q=80'
    },
    {
        image:
            'https://images.unsplash.com/photo-1503177119275-0aa32b3a9368?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1350&q=80'
    }
];

그런 다음 App.js로 이동하여 약간의 코드를 추가합니다.

코드 조각(App.js):

import './App.css';
import ImageSlider from './components/ImageSlider';
import { SliderData } from './components/SliderData';

function App() {
  return <ImageSlider slides={SliderData} />;
}

export default App;

앞서 언급한 CSS는 캐러셀 효과가 원하는 대로 작동하는지 확인하는 데 중요한 역할을 하므로 App.css 파일로 이동하여 몇 가지 조정을 수행합니다.

코드 조각(App.css):

.slider {
  position: relative;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.image {
  width: 1000px;
  height: 600px;
  border-radius: 10px;
}

.right-arrow {
  position: absolute;
  top: 50%;
  right: 32px;
  font-size: 3rem;
  color: #000;
  z-index: 10;
  cursor: pointer;
  user-select: none;
}

.left-arrow {
  position: absolute;
  top: 50%;
  left: 32px;
  font-size: 3rem;
  color: #000;
  z-index: 10;
  cursor: pointer;
  user-select: none;
}

.slide {
  opacity: 0;
  transition-duration: 1s ease;
}

.slide.active {
  opacity: 1;
  transition-duration: 1s;
  transform: scale(1.08);
}

이 모든 코드를 지침에 따라 배치하면 회전 목마 효과가 훌륭하게 작동해야 합니다.

출력:

React Hooks를 사용한 반응형 캐러셀

React Material-UI를 사용한 반응형 캐러셀

React Material-UI는 반응 캐러셀에 대한 탐색 화살표를 설정하기 위해 배포할 기능 라이브러리입니다. 그런 다음 반응 상태 후크를 사용하여 작업을 완료합니다.

새 프로젝트를 만든 후 npm install @material-ui/corenpm install @material-ui/icons를 사용하여 material-UI를 설치합니다.

이제 src로 이동하여 Components, HelpersImages라는 3개의 폴더를 만듭니다. Components 폴더 안에 Carousel.jsCarousel.css를 생성합니다.

Helpers 폴더 안에 CarouselData.js를 만들고 Images 폴더 안에 이미지를 넣습니다. Carousel.js 폴더로 시작하여 다음 코드를 입력합니다.

코드 조각(Carousel.js):

import React, { useState } from "react";
import "./Carousel.css";
import { images } from "../Helpers/CarouselData";
import ArrowBackIosIcon from "@material-ui/icons/ArrowBackIos";
import ArrowForwardIosIcon from "@material-ui/icons/ArrowForwardIos";

function Carousel() {
  const [currImg, setCurrImg] = useState(0);

  return (
    <div className="carousel">
      <div
        className="carouselInner"
        style={{ backgroundImage: `url(${images[currImg].img})` }}
      >
        <div
          className="left"
          onClick={() => {
            currImg > 0 && setCurrImg(currImg - 1);
          }}
        >
          <ArrowBackIosIcon style={{ fontSize: 30 }} />
        </div>
        <div className="center">
          <h1>{images[currImg].title}</h1>
          <p>{images[currImg].subtitle}</p>
        </div>
        <div
          className="right"
          onClick={() => {
            currImg < images.length - 1 && setCurrImg(currImg + 1);
          }}
        >
          <ArrowForwardIosIcon style={{ fontSize: 30 }} />
        </div>
      </div>
    </div>
  );
}

export default Carousel;

여기에서 useState를 사용하여 모든 탐색 작업을 설정하여 onClick 이벤트 리스너를 트리거하는 화살표 중 하나를 클릭할 때 어떤 일이 발생하는지 정의합니다.

그런 다음 Carousel.css를 사용하여 해당 CSS를 설정합니다.

코드 조각(Carousel.css):

.carousel {
    width: 60%;
    height: 700px;
    background-color: black;
}

.carouselInner {
    height: 100%;
    width: 100%;
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
    display: flex;
}

.carouselInner .left {
    flex: 5%;
    height: 100%;
    background-color: rgb(0, 0, 0, 0.6);
    display: grid;
    place-items: center;
    color: white;
    cursor: pointer;
}

.carouselInner .center {
    flex: 80%;
    height: 100%;
    display: grid;
    place-items: center;
    font-family: Arial, Helvetica, sans-serif;
    text-align: justify;
    text-align-last: center;
}

h1 {
    font-size: 5rem;
}

p {
    font-size: 2rem;
}

h1, p {
    background-color: rgb(255, 255, 255, 0.8);
    padding: 20px;
    border-radius: 9px;
}

.carouselInner .right {
    flex: 5%;
    height: 100%;
    background-color: rgb(0, 0, 0, 0.6);
    display: grid;
    place-items: center;
    color: white;
    cursor: pointer;
}

Helpers 폴더에는 CarouselData.js 파일이 있습니다. 이름에서 알 수 있듯이 파일에는 웹 페이지에 표시하려는 이미지와 기타 정보가 들어 있습니다.

코드 조각(CarouselData.js):

import City from "../Images/city.jpg";
import Salvador from "../Images/salvador.jpg";
import Ubc from "../Images/ubc.jpg";

export const images = [
  { title: "San Diego",
  subtitle: "This is San Diego",
  img: City,
  },
  {
    title: "Salvador, Brazil",
    subtitle: "The Best City in the World",
    img: Salvador,
  },
  {
    title: "UBC (Vancouver)",
    subtitle: "The University of British Columbia",
    img: Ubc,
  },
];

마지막으로 App.js에서 약간의 코딩을 수행합니다. 이 파일은 프로젝트가 잘 렌더링되었는지 확인합니다.

코드 조각(App.js):

import "./App.css";
import Carousel from "./Components/Carousel";
import React from "react";
function App() {
  return (
    <div className="App">
      <Carousel />
    </div>
  );
}

export default App;

출력:

React Material-UI를 사용한 반응형 캐러셀

결론

회전 목마 효과는 사용 목적에 관계없이 웹 페이지를 아름답게 합니다. 또한 React 프레임워크는 웹 앱에서 슬라이드 효과를 설정하고 실행하는 다양한 방법을 탐색할 수 있는 매우 유연한 플랫폼을 제공합니다.

Oluwafisayo Oluwatayo avatar Oluwafisayo Oluwatayo avatar

Fisayo is a tech expert and enthusiast who loves to solve problems, seek new challenges and aim to spread the knowledge of what she has learned across the globe.

LinkedIn