React

 

 

 

 npm i swiper

 

https://swiperjs.com/react

// import Swiper core and required modules
import { Navigation, Pagination, Scrollbar, A11y } from 'swiper/modules';

import { Swiper, SwiperSlide } from 'swiper/react';

// Import Swiper styles
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
import 'swiper/css/scrollbar';

export default () => {
  return (
    <Swiper
      // install Swiper modules
      modules={[Navigation, Pagination, Scrollbar, A11y]}
      spaceBetween={50}
      slidesPerView={3}
      navigation
      pagination={{ clickable: true }}
      scrollbar={{ draggable: true }}
      onSwiper={(swiper) => console.log(swiper)}
      onSlideChange={() => console.log('slide change')}
    >
      <SwiperSlide>Slide 1</SwiperSlide>
      <SwiperSlide>Slide 2</SwiperSlide>
      <SwiperSlide>Slide 3</SwiperSlide>
      <SwiperSlide>Slide 4</SwiperSlide>
      ...
    </Swiper>
  );
};

 

 

 

 

freeMode : false, // 슬라이드 넘길 때 위치 고정 여부
autoHeight : true,  // 현재 활성 슬라이드높이 맞게 높이조정
a11y : false, // 접근성 매개변수(접근성 관련 대체 텍스트 설정이 가능) 
resistance : false, // 슬라이드 터치 저항 여부
slideToClickedSlide : true, // 해당 슬라이드 클릭시 슬라이드 위치로 이동
allowTouchMove : true, // (false-스와이핑안됨)버튼으로만 슬라이드 조작이 가능
watchOverflow : true // 슬라이드가 1개 일 때 pager, button 숨김 여부 설정
slidesOffsetBefore : number, // 슬라이드 시작 부분 여백
slidesOffsetAfter : number, 
 

 

 

 

 

 

EX) Row.js

import React, { useCallback, useEffect, useState } from 'react'
import { axiosInnstance } from '../api/axios';
import './Row.css';
import MovieModal from './MovieModal';

import { Autoplay, Navigation, Pagination, Scrollbar, A11y } from 'swiper/modules';
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
import 'swiper/css/scrollbar';
import styled from 'styled-components';




const Row = ({title, id, delay,fetchUrl}) => {
  const [movies, setMovies] = useState([]);
  const [modalOpen, setModalOpen] = useState(false);
  //클릭한 영화 정보 가져오기
  const [movieSelected, setMovieSelection] = useState({});


  const fetchMovieData= useCallback( async () => {
    const response= await axiosInnstance.get(fetchUrl, {});      
    setMovies(response.data.results);
  }, [fetchUrl] );


  useEffect(() =>{
    fetchMovieData();

  }, [fetchMovieData]);


  const handleClick=useCallback((movie)=>{
    console.log("movie ",movie);

    setModalOpen(true);
    setMovieSelection(movie);
  }, [setModalOpen, setMovieSelection]);




  return (
    <Container>
        <h2>{title}</h2>
          
      <Swiper
        modules={[Autoplay, Navigation, Pagination, Scrollbar, A11y]}
        spaceBetween={10}
        slidesPerView={5}
        navigation  //arrow 버튼 사용유무
        pagination={{ clickable: true }} // 페이지 버튼 사용여부
        scrollbar={{ draggable: true }}
        // onSwiper={(swiper) => console.log(swiper)}
        // onSlideChange={() => console.log('slide change')}

        // loop={true} //loop 기능을 사용할지 여부 => 버전업 기본값 true 사용하면 waring
        speed={1500}   //슬라이드 이동 속도  
        autoplay={{
          delay: delay,
          disableOnInteraction: false,
          
        }}
         breakpoints={{
          1968: {
            slidesPerView: 6,
            slidesPerGroup: 6,
          },
          1568: {
            slidesPerView: 5,
            slidesPerGroup: 5,
          },

          1378: {
            slidesPerView: 4,
            slidesPerGroup: 4,
          },

          1060: {
            slidesPerView: 3,
            slidesPerGroup: 3,
          },
          756: {
            slidesPerView: 2,
            slidesPerGroup: 2,
          },

          456: {
            slidesPerView:1,
            slidesPerGroup: 1,
          },
        }}

        className="mySwiper"
      >

        {movies.map((movie, index) => (
          <SwiperSlide 
            className='row__poster' 
            key={index}>
              
            <img 
              key={movie.id}
              src={`https://image.tmdb.org/t/p/w300${movie.backdrop_path}`} 
              alt={movie.title} 
              onClick={()=>handleClick(movie)}              
            />
          </SwiperSlide>
        ))}   

    </Swiper>

        {modalOpen && 
          <MovieModal
            {...movieSelected}
            setModalOpen={setModalOpen}
          />          
        }
          
    </Container>
  )
}

export default Row


const Container=styled.div`
  padding: 0, 0 30px;

`;

 

 

Row.css

.slider {
    position: relative;
    scroll-behavior: smooth !important;
}

.slider__arrow-left {
    background-clip: content-box;
    padding: 20px 0;
    box-sizing: border-box;
    transition: 400ms all ease-in-out;
    cursor: pointer;
    width: 80px;
    z-index: 1000;
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    visibility: hidden;
}

.slider__arrow-right {
    padding: 20px 0;
    background-clip: content-box;
    box-sizing: border-box;
    transition: 400ms all ease-in-out;
    cursor: pointer;
    width: 80px;
    z-index: 1000;
    position: absolute;
    right: 0;
    top: 0;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    visibility: hidden;
}

.arrow {
    transition: 400ms all ease-in-out;
    font-size: 38px;
    font-weight: bold;
}

.arrow:hover {
    transition: 400ms all ease-in-out;
    transform: scale(1.5);

}

.slider:hover .slider__arrow-left {
    transition: 400ms all ease-in-out;
    visibility: visible;
}

.slider:hover .slider__arrow-right {
    transition: 400ms all ease-in-out;
    visibility: visible;
}

.slider__arrow-left:hover {
    background: rgba(20, 20, 20, 0.5);
    transition: 400ms all ease-in-out;
}

.slider__arrow-right:hover {
    background: rgba(20, 20, 20, 0.5);
    transition: 400ms all ease-in-out;
}

.row__posters {
    display: flex;
    overflow-y: hidden;
    overflow-x: scroll;
    padding: 20px 0 20px 20px;
    scroll-behavior: smooth !important;
    cursor: pointer;
}

.row__posters::-webkit-scrollbar {
    display: none;
}

.row__poster {
    object-fit: contain;
    width: 100%;
    max-height: 144px;
    margin-right: 10px;
    transition: transform 450ms;
    border-radius: 4px;
}

.row__poster:hover {
    transform: scale(1.08);
}

.row__posterLarge {
    max-height: 320px;
}

.row__posterLarge:hover {
    transform: scale(1.1);
    opacity: 1;
}

.row__arrow-left {
    position: absolute;
    top: 0;
    left: 20px;
    height: 100%;
    width: 32px;
    background: rgba(0, 0, 0, 0.2);
    display: flex;
    align-items: center;
}

.row__arrow-right {
    position: absolute;
    top: 0;
    right: 0px;
    height: 100%;
    width: 32px;
    background: rgba(0, 0, 0, 0.2);
    display: flex;
    align-items: center;
}

@media screen and (min-width: 1200px) {
    .row__poster {
        max-height: 160px;
    }

    .row__posterLarge {
        max-height: 360px;
    }
}

@media screen and (max-width: 768px) {
    .row__poster {
        max-height: 100px;
    }

    .row__posterLarge {
        max-height: 280px;
    }
}



.swiper-pagination{
    text-align: right !important;
}

.swiper-pagination-bullet{
    background: gray !important;
    opacity: 1 !important;
}

.swiper-pagination-bullet-active{
    background-color: #fff !important;
}

.swiper-horizontal {
    text-align: center !important;
}
.swiper .swiper-button-next, .swiper .swiper-button-prev{
    color: #fff;
}
.row__poster{
    cursor: pointer;
}

 

 

 

 

소스 :

https://github.com/braverokmc79/react-disney-plus-app

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

마음에 진실이 없는 자는 그들의 거짓말 전부를 지껄여 대지 못하는 것이다. -대학

댓글 ( 0)

댓글 남기기

작성

React 목록    more