React-nodebird -05

이미지 캐러셀

현재 내가 만들고 있는 트위터 비슷한 이 노드버드 프로젝트에는 사람들이 게시글을 올릴 수 있고, 그 게시글에는 기본 글 외에도 이미지,해쉬태그 등을 올릴 수 있을 것이다.

이미지 작업을 해보자.

우선 post reducer의 맨 처음 게시글에는 3종류의 이미지를 넣어주었다.
지금은 이미지를 3개만 올렸기 때문에 크게 문제가 되지는 않지만, 만약 많은 수의 이미지를 넣었다면 ? 게시글의 길이가 너무 길어지거나 (이미지의 양 때문에) 게시글이 원하는 형식처럼 보이지 않을 것이다.

따라서 게시글에 들어있는 이미지가 3개 이상일 때 이미지 캐러샐을 이용해서 클릭해서 잘 볼 수 있는 기능을 만들 것이다.

이미지 캐러셀이란 이미지를 슬라이드 시켜서 가로로 볼 수 있는 것을 말한다.

그렇다면 이 기능을 어떻게 사용해야 할까 ?

react-slick 라이브러리가 있다. 이 라이브러리를 이용해서 공식문서를 참조하면 쉽게 이미지 캐러셀을 구현할 수 있는데,

맨 처음에는 이 라이브러리만 사용하면 되는 것인 줄 알고 무작정 진행하다가 오류가 났다. react-slick이 오류 나지 않게 형식을 또 맞춰주어야만 한다.

이런식으로 이미지가 이상한 곳에 나타난다.

import styled, { createGlobalStyle } from "styled-components";
import { CloseOutlined } from "@ant-design/icons";

export const Global = createGlobalStyle`
  .slick-slide {
    display: inline-block;
  }
  .ant-card-cover {
    transform: none !important;
  }
`;

export const Overlay = styled.div`
    position: fixed;
    z-index: 5000;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
`;

export const Header = styled.header`
    height: 44px;
    background: white;
    position: relative;
    padding: 0;
    text-align: center;

    & h1 {
        margin: 0;
        font-size: 17px;
        color: #333;
        line-height: 44px;
    }
`;

export const SlickWrapper = styled.div`
    height: calc(100% - 44px);
    background: #090909;
`;

export const CloseBtn = styled(CloseOutlined)`
    position: absolute;
    right: 0;
    top: 0;
    padding: 15px;
    line-height: 14px;
    cursor: pointer;
`;

export const Indicator = styled.div`
    text-align: center;

    & > div {
        width: 75px;
        height: 30px;
        line-height: 30px;
        border-radius: 15px;
        background: #313131;
        display: inline-block;
        text-align: center;
        color: white;
        font-size: 15px;
    }
`;

export const ImgWrapper = styled.div`
    padding: 32px;
    text-align: center;

    & img {
        margin: 0 auto;
        max-height: 750px;
    }
`;

이렇게 styled-components를 이용해서 형식을 맞춰주고 사용해야하는 것이었다.

//component 가 많아지고 복잡해지면 이렇게 폴더 안에 만듬.
//why ?
import React, { useState } from "react";
import PropTypes from "prop-types";
import Slick from "react-slick";
import {
    Overlay,
    Header,
    CloseBtn,
    SlickWrapper,
    ImgWrapper,
    Indicator,
    Global,
} from "./styles";

const ImagesZoom = ({ images, onClose }) => {
    const [currentSlide, setCurrentSlide] = useState(0);
    return (
        <Overlay>
            <Global />
            <Header>
                <h1>상세 이미지</h1>
                <CloseBtn onClick={onClose} />
            </Header>
            <SlickWrapper>
                <div>
                    <Slick
                        initialSlide={0}
                        beforeChange={(slide, newSlide) =>
                            setCurrentSlide(newSlide)
                        }
                        infinite
                        arrows={false}
                        slidesToShow={1}
                        slidesToScroll={1}
                    >
                        {images.map((v) => (
                            <ImgWrapper key={v.src}>
                                <img src={v.src} alt={v.src} />
                            </ImgWrapper>
                        ))}
                    </Slick>
                    <Indicator>
                        <div>
                            {currentSlide + 1} /{images.length}
                        </div>
                    </Indicator>
                </div>
            </SlickWrapper>
        </Overlay>
    );
};

ImagesZoom.propTypes = {
    images: PropTypes.arrayOf(PropTypes.object).isRequired,
    onClose: PropTypes.func.isRequired,
};

export default ImagesZoom;

그후에는 공식 문서를 보고 Slick을 사용하면 된다.

강의는 여기서 넘어가는데 esc키를 누르면 state를 변경해서 Slick을 종료하고 싶다면 어떻게 해야할까 ?

Slick을 포함하고 있는 컴포넌트의 가장 바깥 컴포넌트인 Overlay에 onKeyDown을 주면 된다.

const exit = useCallback((e)=>{
	if(e.keyCode === 27){
    	onClose();
    }
},[]);

이런식으로 하면 버튼을 누를 때 뿐만 아니라 내가 esc키를 눌렀을 때도 slick을 종료할 수 있다.

좋은 웹페이지 즐겨찾기