MUI
MUI - 모달로 슬라이더 만들기
AgileJung
2022. 7. 29. 05:00
728x90
반응형
MUI의 모달을 사용하여 모달 안에서 슬라이드를 구현해보자.
import 부분
나는 Marsonry라는 레이아웃을 적용하였다. 똑같이 적용하고 싶다면 @mui/lab을 설치하면 된다.
import React, { useState } from 'react';
import styled from '@emotion/styled';
import { Masonry } from '@mui/lab';
import { Box, Modal, IconButton, Typography } from '@mui/material';
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
함수 동작 부분
const [open, setOpen] = useState(false);
const [imgindex, setImgindex] = useState(0);
const handleOpen = index => {
setImgindex(index.target.id);
setOpen(true);
};
const handleClose = () => setOpen(false);
const backImg = () => {
Number(imgindex) === 0
? setImgindex(movie_image.length - 1)
: setImgindex(imgindex - 1);
};
const forwardImg = () => {
setImgindex(Number(imgindex) + 1);
if (imgindex === movie_image.length - 1) {
setImgindex(0);
}
};
주의할점!
자바스크립트는 +와 - 를 문자와 숫자를 같은 타입이라고 생각하고 그대로 문자와 숫자를 더해버리기 때문에
숫자로만 판별해야 하는 조건에서는 Number()를 통해서 문자가 아닌 숫자라고 정해줘야 오류가 나지 않는다.
컴포넌트 UI 부분
<Box>
<GalleryModal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
img={movie_image}
imgindex={imgindex}
>
<ImgContainer>
<GalleryButton sx={{ marginLeft: '-80px' }} onClick={backImg}>
<ArrowBackIosIcon />
</GalleryButton>
<Img
src={movie_image[imgindex]}
img={movie_image}
imgindex={imgindex}
/>
<GalleryButton sx={{ marginLeft: '50px' }} onClick={forwardImg}>
<ArrowForwardIosIcon />
</GalleryButton>
<Box sx={{ textAlign: 'center', marginTop: '10px' }}>
<NowImg>{Number(imgindex) + 1}</NowImg>
<TotalImg> /{movie_image.length}</TotalImg>
</Box>
</ImgContainer>
</GalleryModal>
</Box>
전체 코드
import React, { useState } from 'react';
import styled from '@emotion/styled';
import { Masonry } from '@mui/lab';
import { Box, Modal, IconButton, Typography } from '@mui/material';
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
function MovieGallery({ movie_image }) {
const [open, setOpen] = useState(false);
const [imgindex, setImgindex] = useState(Number(0));
const handleOpen = index => {
setImgindex(index.target.id);
setOpen(true);
};
const handleClose = () => setOpen(false);
const backImg = () => {
Number(imgindex) === 0
? setImgindex(Number(movie_image.length) - 1)
: setImgindex(Number(imgindex) - 1);
};
const forwardImg = () => {
setImgindex(Number(imgindex) + 1);
if (imgindex === movie_image.length - 1) {
setImgindex(0);
}
};
return (
<>
<Box sx={{ width: '100%', minHeight: 429 }}>
<Masonry columns={4} spacing={2}>
{movie_image?.map((item, index) => (
<div key={index}>
<MasonryImg
id={index}
src={`${item}?w=162&auto=format`}
srcSet={`${item}?w=162&auto=format&dpr=2 2x`}
alt={item.title}
loading="lazy"
onClick={handleOpen}
style={{
borderRadius: 8,
borderBottomLeftRadius: 8,
borderBottomRightRadius: 8,
display: 'block',
width: '100%',
boxShadow: '5px 7px 20px -4px rgba(0, 0, 0, 0.6)',
}}
/>
</div>
))}
</Masonry>
</Box>
<Box>
<GalleryModal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
img={movie_image}
imgindex={imgindex}
>
<ImgContainer>
<GalleryButton sx={{ marginLeft: '-80px' }} onClick={backImg}>
<ArrowBackIosIcon />
</GalleryButton>
<Img
src={movie_image[imgindex]}
img={movie_image}
imgindex={imgindex}
/>
<GalleryButton sx={{ marginLeft: '50px' }} onClick={forwardImg}>
<ArrowForwardIosIcon />
</GalleryButton>
<Box sx={{ textAlign: 'center', marginTop: '10px' }}>
<NowImg>{Number(imgindex) + 1}</NowImg>
<TotalImg> /{movie_image.length}</TotalImg>
</Box>
</ImgContainer>
</GalleryModal>
</Box>
</>
);
}
export default MovieGallery;
const ImgContainer = styled(Box)`
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 800px;
box-shadow: 24px;
padding: 40px;
outline: none;
`;
const MasonryImg = styled.img`
cursor: pointer;
transition: all ease 0.5s;
:hover {
transform: scale(1.04, 1.04);
}
`;
const Img = styled.img`
border-radius: 16px;
width: 100%;
`;
const GalleryButton = styled(IconButton)`
position: absolute;
top: 50%;
`;
const GalleryModal = styled(Modal)``;
const NowImg = styled(Typography)`
display: inline;
color: white;
font-weight: bold;
`;
const TotalImg = styled(NowImg)``;
728x90
반응형