ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • MUI - 모달로 슬라이더 만들기
    MUI 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
    반응형

    'MUI' 카테고리의 다른 글

    Mui - Progressbar  (0) 2022.07.20
    MUI - TextField  (0) 2022.07.16
    MUI - Box  (0) 2022.07.16
    MUI를 사용하는 방법  (0) 2022.07.06

    댓글

Designed by Tistory.