캐러셀 슬라이드

박은정·2021년 9월 18일
0

TIL

목록 보기
64/70

본인이 직접 작성한 코드가 아닌, 다른 사람의 코드를 보고 해석하려는 의도로 블로그를 작성합니다..!
출처 : https://github.com/wecode-bootcamp-korea/24-2nd-FX-frontend/blob/feature/Carousel/src/Components/Carousel.js

전체 레이아웃 구성

<Container>
  <HeaderBox
  onMouseEnter={showHiddenHeader}
  onMouseLeave={hideHiddenHeader}>
    <Header>지금 뜨는 콘텐츠 </Header>
    <HiddenHeader hiddenStatus={hiddenStatus}>
    모두 보기 &#62;
    </HiddenHeader>
    <button onClick={handleModal}>모달열기</button>
  </HeaderBox>
       
  <Slider>
    <LeftArrow onClick={handleLeftArrow}>&#60;</LeftArrow>
    
    <CardWrapper curXAxis={curXAxis}>
    {cardsData.map(card => {
      return (
        <Card
          id={card.id}
          img={card.thumb_nail}
          onClick={handleModal}/>
      );
    })}
    </CardWrapper>
    
    <RightArrow onClick={handleRightArrow}>&#62;</RightArrow>
  </Slider>

  <ModalPortal>
    <Modal onClose={handleModal} modalOn={modalOn} />
  </ModalPortal>
</Container>

1️⃣ Header Box 요소

실제 레이아웃 구성

<HeaderBox
  onMouseEnter={showHiddenHeader}
  onMouseLeave={hideHiddenHeader}>
    <Header>지금 뜨는 콘텐츠 </Header>
    <HiddenHeader hiddenStatus={hiddenStatus}>
    모두 보기 &#62;
    </HiddenHeader>
    <button onClick={handleModal}>모달열기</button>
</HeaderBox>

const 선언

const showHiddenHeader = () => {
  setHiddenStatus(true);
};

const hideHiddenHeader = () => {
  setHiddenStatus(false);
};

const handleModal = () => {
  setModalOn(!modalOn);
};

const [hiddenStatus, setHiddenStatus] = useState(false);
const HeaderBox = styled.div`
  margin-bottom: 15px;
  margin-left: 50px;
  color: #e5e5e5;
`;

const Header = styled.span`
  font-size: 20px;
  font-weight: 700;
`;


const HiddenHeader = styled.span`
  font-size: 12px;
  font-weight: 600;
  display: ${props => (props.hiddenStatus ? "inline-block" : "none")};
  animation: ${fadein} 0.3s;
`;

이번에 처음 본 내용

1. onMouseEnter() 메서드

  • 마우스 포인터를 이미지로 이동할 때 JavaScript를 실행한다
  • 마우스 포인터가 요소 안으로 들어올 때(자식 포함) 발생하는 이벤트
  • 요소 밖으로 나갔다 오지 않으면 계속 발생하지 않음

2. onMouseLeave() 메서드

이미지 밖으로 마우스 포인터를 이동할 때 JavaScript를 실행한다

3. onmouseenter() vs onmouseover() 차이점

  1. onmouseenter와 onmouseover는 모두 마우스가 요소의 경계에 들어갈 때 실행되는 점은 동일하다
  2. 마우스가 이 첫 번째 요소 내의 자식 요소에 들어가면 onmouseenter가 다시 실행되지 않는다 : 이를 버블하지 않는다고 한다
    • onmouseover 이벤트와 달리 onmouseenter 이벤트는 버블링되지 않기 때문에
    • 사용자가 개체에 포함된 요소 위로 마우스 포인터를 이동할 때 onmouseenter 이벤트가 발생하지 않는 반면 onmouseover는 발생한다

4. :hover 같은 CSS 동작을 적용하지 않는이유는?

CSS동작은 스레드의 실행이 중지될 때마다 실행되기 때문에 속도가 느리다
그리고 :hover 동작은 IE6에서는 작동하지 않는다

Header Box 요소 : 코드해석

HeaderBox 요소에
마우스포인터를 이동했을 때 showHiddenHeader() 함수를 실행하고
해당요소 밖으로 마우스포인터를 이동했을 때 hideHiddenHeader() 함수를 실행한다

HiddenHeader 요소의 기본 hiddenStatus 상태값은 false인데
HeaderBox 요소에 마우스포인터를 이동했을 때, showHiddenHeader()가 실행되면 ture로 바뀌고
HeaderBox 요소 밖으로 마우스 포인터가 이동했을 때, hideHiddenHeader()가 실행되면 다시 false로 바뀐다

여기서 hiddenStatus 변수는 HiddenHeader의 display속성값에 대해서 아래와 같이, 조건에 따라 보이거나 보이지 않게 설정할 때 쓰인다

display: ${props => (props.hiddenStatus ? "inline-block" : "none")};

hiddenStatus = false → display: none
hiddenStatus = true → display: nline-block

2️⃣ Slider 요소

실제 레이아웃 구성

  <Slider>
    <LeftArrow onClick={handleLeftArrow}>&#60;</LeftArrow>
    
    <CardWrapper curXAxis={curXAxis}>
    {cardsData.map(card => {
      return (
        <Card
          id={card.id}
          img={card.thumb_nail}
          onClick={handleModal}/>
      );
    })}
    </CardWrapper>
    
    <RightArrow onClick={handleRightArrow}>&#62;</RightArrow>
  </Slider>

const 선언

import Card from "./Card";

const handleLeftArrow = () => {
    if (curXAxis < 0) {
      setCurXAxis(curXAxis + imgWidth * 8);
    }
  };

  const handleRightArrow = () => {
    if (curXAxis > (totalCount - 8) * -imgWidth) {
      setCurXAxis(curXAxis - imgWidth * 8);
    }
  };

const Slider = styled.div`
  display: flex;
  position: relative;
`;

const CardWrapper = styled.ul`
  display: flex;
  z-index: 0;
  margin-left: 50px;
  transform: translateX(${props => props.curXAxis}px);
  transition: all 0.7s ease-in-out;
`;

const Arrow = styled.button`
  position: absolute;
  top: 100px;
  direction: ${props => props.direction};
  color: #e5e5e5;
  opacity: 0.5;
  font-size: 60px;
  cursor: pointer;
  z-index: 1;
  &:hover {
    opacity: 1;
  }
`;

const LeftArrow = styled(Arrow.withComponent("button"))`
  left: 0px;
`;

const RightArrow = styled(Arrow.withComponent("button"))`
  right: 0px;
`;

이번에 처음 본 내용

1. &#60; : 특수문자 숫자표현

이게 뭔지 몰라서 구글검색창에 &#60;이라고 검색하니까 < 이라고 검색된다

그래서 어떤건지 찾아봤는데 유니코드 특수문자 리스트 이러한 사이트에서

< 이라는 표현문자를 나타내는 숫자표현이었다
HTML 상에서 특수문자가 제대로 나타나지 않을 수 있기 때문에 아래 문자들를 사용한다고 한다

2. .withComponent() 메서드

1) 새로운 styled-component를 생성하고 다른 태그에 적용시킨다
일단 이 코드를 먼저 보자면, Arrow라는 styled-component를 button태그에 적용했고

Arrow.withComponent("button")

2) CSS를 추가하고 싶으면 아래와 같이 styled()'' 메서드를 사용하면 된다

styled(Arrow.withComponent("button"))`
  left: 0px;
`;

그래서 아래의 LeftArrow, RightArrow 컴포넌트를 해석하자면

const LeftArrow = styled(Arrow.withComponent("button"))`
  left: 0px;
`;

const RightArrow = styled(Arrow.withComponent("button"))`
  right: 0px;
`;

Arrow 컴포넌트의 스타일속성을 button 태그에 입혀주고
각각 아래의 스타일 속성을 추가해줬다
LeftArrow 컴포넌트에는 left: 0px
RightArrow 컴포넌트에는 right: 0px

Slider 요소 : 코드해석

슬라이더의 < > 버튼

<LeftArrow onClick={handleLeftArrow}>&#60;</LeftArrow>
<RightArrow onClick={handleRightArrow}>&#62;</RightArrow>

const imgWidth = 180;
const totalCount = 21;
const handleLeftArrow = () => {
    if (curXAxis < 0) {
      setCurXAxis(curXAxis + imgWidth * 8);
    }
  };

  const handleRightArrow = () => {
    if (curXAxis > (totalCount - 8) * -imgWidth) {
      setCurXAxis(curXAxis - imgWidth * 8);
    }
  };
  • LeftArrow 버튼을 눌렀을 때 발생하는 handleLeftArrow() 함수
    : curXAxis가 0보다 작은 상태라면 이미지너비 * 8 만큼 더해주고

  • RightArrow 버튼을 눌렀을 때 발생하는 handleRightArrow() 함수
    : curXAxis가 (totalCount - 8) * -imgWidth 보다 큰 상태라면 imgWidth * 8 만큼 빼준다

💡 질문하기!!

조건에 충족하지 않는 경우에는 어떻게 작동하는가??

  • LeftArrow 버튼을 눌렀을 때 curXAxis가 0보다 크거나
  • RightArrow 버튼을 눌렀을 때 (totalCount - 8) * -imgWidth보다 작은 상태일 때
  • 어떤 로직으로 슬라이더가 작동하는건지...

CardWrapper

<CardWrapper curXAxis={curXAxis}>
    {cardsData.map(card => {
      return (
        <Card
          id={card.id}
          img={card.thumb_nail}
          onClick={handleModal}/>
      );
    })}
</CardWrapper>

const [curXAxis, setCurXAxis] = useState(0);
const [cardsData, setCardsData] = useState([]);
const updateCardsData = data => {
      setCardsData(data.Result);
    };
const CardWrapper = styled.ul`
  display: flex;
  z-index: 0;
  margin-left: 50px;
  transform: translateX(${props => props.curXAxis}px);
  transition: all 0.7s ease-in-out;
`;

curXAxis 변수에 따라 좌우로 이동하고
cardsData 배열의 요소를 map() 메서드를 이용해서 Card 컴포넌트를 반복해서 구현하는데

💡 handleFetch() 함수

초기값이 빈 배열인 cardsData의 상태를 변화시켜주는 setCardsData() 메서드는 handleFetch() 함수에서 사용되지만 이 부분도 더 공부할 필요가 있다...

handleFetch(`${MainAPI}/list?${paramsString}`, updateCardsData);
  }, []);

Card 컴포넌트에 id, img, onClick이벤트 함수를 전달하는데
그 중에서 handleModal() 함수는

const [modalOn, setModalOn] = useState(false);

  const handleModal = () => {
    setModalOn(!modalOn);
  };

기본적으로 false인 modalOn를
handleModal() 함수를 호출하게 되면 true로 바꾸고
그 상태에서 다시 handleModal() 함수를 호출하게 되면
원래 modalOn 상태인 false로 바뀌게 된다

Card 컴포넌트

<li>
  <ImgBox
    id={props.id}
    src={props.img}
    alt="imgbox"
    onClick={props.onClick}
  />
</li>

const ImgBox = styled.img`
  width: 200px;
  height: 280px;
  border-radius: 10px;
  margin-left: 7px;
  cursor: pointer;
  &:hover {
    transform: scale(1.1);
    transition: transform 0.35s;
  }
`;

props로 전달받은 id, img, onClick이벤트를 받은 img태그이다

3️⃣ ModalPortal 요소

실제 레이아웃 구성


const [modalOn, setModalOn] = useState(false);
  <ModalPortal>
    <Modal onClose={handleModal} modalOn={modalOn} />
  </ModalPortal>

const 선언

import ModalPortal from "../Components/Modal/Portal";
import Modal from "./Modal/Modal";

Portal.js 에서 불러온 ModalPortal 컴포넌트 내부에
Modal.js 에서 불러온 Modal 컴포넌트로 구성되어있다

profile
새로운 것을 도전하고 노력한다

0개의 댓글