Swiperjs 커스터마이징 / react, styled-components

minkyung·2023년 6월 2일
0
post-thumbnail

요구사항
1. enable/disable 일 때 svg 컬러 다르게
2. 각각 left/right 화살표 mouseOver 시 화살표 꼬리 애니메이션 넣기


기본 틀

📎 [swiperjs 공식문서] react#usage

import SwiperCore, { Navigation } from "swiper";

SwiperCore.use([Navigation]);

<S.SlideContainer>
 <S.ArrowDirection className="swiper-prev" />
   <Swiper
   spaceBetween={20}
   slidesPerView={1}
   navigation={{
         nextEl: ".swiper-next",
         prevEl: ".swiper-prev",
         }}
         >
           {data.map(()=>{
             return (
               <SwiperSlide>
               슬라이드 내용
               </SwiperSlide>
             );
           })}
   </Swiper>
 <S.ArrowDirection className="swiper-next" />
</S.SlideContainer>

navigation={{nextEl: ".swiper-next", prevEl: ".swiper-prev"}}

  • nextEl, prevEl를 className으로 지정함
  • 해당 버튼 누르면 슬라이드 넘어가고 (prev:왼쪽, next:오른쪽)
  • 슬라이드 개수 1개일 경우에 알아서 해당 클래스 element가 숨겨지고,
  • 슬라이드 끝과 끝(beginning, end)에 오면 자동으로 해당 element에 disabled className이 붙음
  • swiper/css 그대로 가져오는 것보다 커스터마이징하기에 이게 편함

ArrowDirection은 이렇게 생김 ↓


1. enable/disable 일 때 svg 컬러 다르게

  • 슬라이드 끝과 끝(beginning, end)에 오면 자동으로 해당 element에 disabled className이 붙음

☃︎ disabled className으로 disable일 때의 스타일링 가능

/*Arrow라는 한 쪽 방향의 화살표 svg를 스타일컴포넌트로 확장해서 사용*/
export const ArrowDirection = styled(Arrow)`

	/*공통 스타일링*/
  position: relative;
  z-index: 2;
  stroke: #ededed;
  cursor: pointer;
  min-width: 16px;
  
  /*왼쪽 화살표 스타일링*/
  &.swiper-prev {
    margin-right: 14px;
    transform: scaleX(-1);
  }

  /*오른쪽 화살표 스타일링*/
  &.swiper-next {
    margin-left: 14px;
  }

  /*비활성화된 화살표 스타일링*/
  &.swiper-button-disabled,
  &.swiper-button-disabled {
    stroke: #555;
    cursor: default;
  }
`;

2. 각각 left/right 화살표 mouseOver 시 화살표 꼬리 애니메이션 넣기 (>) (→)

이렇게 변한다는 뜻 ↓

1. 꼬리 div (-) 추가
ArrowHover라는 이름으로 스타일컴포넌트 생성

import SwiperCore, { Navigation } from "swiper";

SwiperCore.use([Navigation]);

<S.SlideContainer>
+ <S.ArrowHover className="leftHover" /> 
 <S.ArrowDirection className="swiper-prev" />
   <Swiper
   spaceBetween={20}
   slidesPerView={1}
   navigation={{
         nextEl: ".swiper-next",
         prevEl: ".swiper-prev",
         }}
         >
           {data.map(()=>{
             return (
               <SwiperSlide>
               슬라이드 내용
               </SwiperSlide>
             );
           })}
   </Swiper>
 <S.ArrowDirection className="swiper-next" />
+ <S.ArrowHover className="rightHover" />
</S.SlideContainer>

스타일링
왼쪽 방향을 기본 값으로 둠
ArrowHover는 걍 > 에 붙이는 하얀 꼬리임

export const ArrowHover = styled.div`
  background-color: #fff;
  /*ArrowDirection이랑 형제로 잡혀있어서 absolute로 정렬 가능*/
  position: absolute;
  width: 17px;
  height: 2px;
  z-index: 3;
  border-radius: 100px;
  opacity: 0;
  pointer-events: none;

  &.rightHover {
    right: 5px;
  }
`;

2. 상황에 맞게 움직이게 하기
1. ArrowDirection(>)이 hover 일 때
2. 해당 (>)이 enable 상태일 때
3. 해당 (>)과 맞는 ArrowHover(-)가 노출되어야함

⚠️
처음에는 Swipe hook 중에 onReachBeginning, onReachEnd를 사용해서
현재 슬라이드가 첫번째 슬라이드(beginning, 왼쪽 화살표 비활성화)인지
마지막 슬라이드(end, 오른쪽 화살표 비활성화)인지
state 값으로 구분해서 props 내려주고 별 쌩쇼를 다했는데

해당 hook을 사용하면
1. 해당하는 element에 자동으로 붙었던 disabled className이 붙지 않고,
2. 슬라이드가 1개여도 화살표가 보이는 상황이 생겨서
그냥 스타일링으로 다 함

[공식문서] swiper-props
[공식문서] swiper-events

export const ArrowDirection = styled(Arrow)`
  position: relative;
  z-index: 2;
  stroke: #ededed;
  cursor: pointer;
  min-width: 16px;

  &.swiper-prev {
    margin-right: 14px;
    transform: scaleX(-1);

	/*왼쪽 화살표(<)에 마우스오버했을 때, 왼쪽 꼬리만 보이게(-)*/
+   :hover {
+     & ~ ${ArrowHover}.leftHover {
+       left: 5px;
+       opacity: 1;
+       animation-name: loading;
+       animation-duration: 300ms;
+       animation-iteration-count: initial;
+       animation-timing-function: ease-out;
+     }
+   }
  }

  &.swiper-next {
    margin-left: 14px;

	/*오른쪽 화살표(>)에 마우스오버했을 때, 오른쪽 꼬리만 보이게(-)*/
+   :hover { 
+     & ~ ${ArrowHover}.rightHover {
+       right: 5px;
+       opacity: 1;
+       animation-name: loading;
+       animation-duration: 300ms;
+       animation-iteration-count: initial;
+       animation-timing-function: ease-out;
+     }
+   }
  }
  
  &.swiper-button-disabled,
  &.swiper-button-disabled {
    stroke: #555;
    cursor: default;
    /*disabled됐을 때에는 hover action 일어나지 않게*/
+   pointer-events: none; 
  }

+  @keyframes loading {
+    0% {
+      width: 0;
+      opacity: 1;
+    }
+
+    90% {
+      width: 17px;
+      opacity: 1;
+    }
+
+    100% {
+      width: 17px;
+      opacity: 1;
+    }
+  }
`;
profile
프론트엔드 개발자

0개의 댓글