혼자 이것저것 공부해보는/디즈니 앱 플러스 클론 코딩
swiper 모듈을 이용한 터치 슬라이드 구현하기
silver님
2024. 8. 1. 16:55
swiper 모듈을 이용한 터치 슬라이드 구현하기
● Swiper 모듈 설치
npm install swiper --save
Row.js
import axios from '../api/axios';
import React, { useCallback, useEffect, useState } from 'react';
import "./Row.css";
import MovieModal from './MovieModal';
import { Navigation, Pagination, Scrollbar, A11y } from 'swiper/modules';
import { Swiper, SwiperSlide } from 'swiper/react';
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/scrollbar";
import "swiper/css/pagination";
import styled from 'styled-components';
const Row = ({ title, id, fetchUrl }) => {
const [Movies, setMovies] = useState([]); // 초기 상태를 빈 배열로 설정
const [modalOpen, setModalOpen] = useState(false);
const [movieSelected, setMovieSelection] = useState({});
const fetchMovieData = useCallback(async () => {
try {
const response = await axios.get(fetchUrl);
console.log('response', response);
setMovies(response.data.results);
} catch (error) {
console.error('Failed to fetch movies:', error);
}
}, [fetchUrl]);
useEffect(() => {
fetchMovieData();
}, [fetchMovieData]);
const handleClick = (movie) => {
setModalOpen(true);
setMovieSelection(movie);
}
return (
<Container>
<h2>{title}</h2>
<Swiper
// install Swiper modules
modules={[Navigation, Pagination, Scrollbar, A11y]}
loop={true} // loop 기능을 사용할 것인지
navigation // arrow 버튼 사용 유무
pagination={{ clickable: true }} // 페이지 버튼 보이게 할지
breakpoints={{
1378: {
slidesPerView: 6, // 한번에 보이는 슬라이드 개수
slidesPerGroup: 6,
},
998: {
slidesPerView: 5, // 한번에 보이는 슬라이드 개수
slidesPerGroup: 5,
},
625: {
slidesPerView: 4, // 한번에 보이는 슬라이드 개수
slidesPerGroup: 4,
},
0: {
slidesPerView: 3, // 한번에 보이는 슬라이드 개수
slidesPerGroup: 3,
},
}}
>
<Content id={id}>
{Movies && Movies.map(movie => (
<SwiperSlide key={movie.id}>
<Wrap>
<img
src={`https://image.tmdb.org/t/p/original/${movie.backdrop_path}`}
alt={movie.name} // alt 속성 추가
onClick={() => handleClick(movie)}
/>
</Wrap>
</SwiperSlide>
))}
</Content>
</Swiper>
{modalOpen && (
<MovieModal
{...movieSelected}
setModalOpen={setModalOpen}
/>
)}
</Container>
);
};
export default Row;
const Container = styled.div`
padding: 0 0 26px;
`;
const Content = styled.div``;
const Wrap = styled.div`
width: 95%;
height: 95%;
padding-top: 56.25%;
border-radius: 10px;
box-shadow: rgb(0 0 0/69%) 0px 26px 30px -10px,
rgb(0 0 0/73%) 0px 16px 10px -10px;
cursor: pointer;
overflow: hidden;
position: relative;
transition: all 250ms cubic-bezier(0.25, 0.46, 0.45, 0.94) 0s;
border: 3px solid rgba(249, 249, 249, 0.1);
img {
inset: 0px;
display: block;
height: 100%;
object-fit: cover;
opacity: 1;
position: absolute;
width: 100%;
transition: opacity 500ms ease-in-out;
z-index:1;
}
&:hover {
box-shadow: rgb(0 0 0 / 80%) 0px 40px 58px -16px,
rgb(0 0 0 / 72%) 0px 30px 22px -10px;
transform: scale(0.98);
border-color: rgba(249, 249, 249, 0.8);
}
`;
Row.css
.swiper-pagination {
text-align: right !important;
}
.swiper-pagination-bullet {
background: gray !important;
opacity: 1 !important;
}
.swiper-pagination-bullet-active {
background-color: white !important;
}
.swiper-button-prev {
color: white !important;
}
.swiper-button-next {
color: white !important;
}
.swiper-button-next::after, .swiper-button-prev::after {
font-size: 1.3rem !important;
font-weight: 600 !important;
}
728x90
반응형