Swiper AutoPlay 기능 및 Progress Bar 구현
1. 개요
pmi 게이트웨이의 공지사항을 보여주는 바를 보시면 현재 autoPlay기능으로 자동으로 다음 슬라이드를 보여주고 있습니다. 하지만 언제 슬라이드가 넘어갈지 몰라서 답답함을 경험해보신 적 한번씩 있으신가요?
Nexon DF 넥슨의 공지사항 바를 살펴보면 이렇게 총 공지사항의 수와 다음 슬라이드로 언제쯤 이동되는지 progress bar를 통해 보여주고 있습니다. 이러한 작은 기능들이 사용자의 편리성을 더 높혀줄 것 같습니다.
그래서 이런 예시를 바탕으로 pmi 직원들의 편의성을 향상 시키기 위해 gateway의 기본적인 autoPlay 슬라이더에 progress bar를 만들고, 마우스 hover 시에 슬라이드를 정지/재개하는 기능을 구현해 보았습니다.
2. Swiper AutoPlay 살펴보기, Event / Parameters
progress를 어떻게 구현하면 좋을까요? 슬라이드 전환 시간에 맞춰 진행 상태를 업데이트하려면 setInterval() 함수로 시간을 수동으로 관리해야 할 것 입니다. 여기에 마우스 이벤트에 따라 정지, 재생하는 기능까지 추가한 예시코드를 보여드리겠습니다.
useEffect(() => {
if (!isPaused) {
intervalRef.current = setInterval(() => {
setProgress(prevProgress => {
if (prevProgress >= 100) {
return 0; // progress가 100%가 되면 초기화
}
return prevProgress + (100 / (slideDuration / 100)); // 매 10ms마다 progress 증가
});
}, 10); // 10ms마다 업데이트
} else {
clearInterval(intervalRef.current); // pause 상태에서는 진행 중인 interval 정지
}
return () => clearInterval(intervalRef.current); // 컴포넌트 unmount 시 interval 정리
}, [isPaused]);
const handleMouseEnter = () => {
setIsPaused(true); // 마우스 올리면 멈춤
};
const handleMouseLeave = () => {
setIsPaused(false); // 마우스 벗어나면 재개
};
이렇게만 봐도 복잡해 보입니다.. 하지만!
Swiper에서는 초창기부터 진행 상태를 보여주는 progress 기능을 제공해 오고 있습니다. Swiper의 progress는 기본적으로 슬라이드가 진행되는 동안, 슬라이드의 이동 상태를 백분율로 추적하여 화면에 표시할 수 있도록 해주는 기능입니다. 이 기능을 사용하면 복잡한 로직없이 손쉽게 progress Bar를 만들 수 있습니다.
이제부터 Swiper의 progress기능을 이용해서 슬라이더의 progress Bar를 만들어보도록 하겠습니다. 밑에는 기본적인 AutoPlay의 API 명세서(swiper-api#autoplay)를 통해 가져온 내용입니다.
- Autoplay Parameters
Name | Type | Default | Description |
---|---|---|---|
delay |
number | 3000 | 전환 사이의 지연 시간 (ms 단위). 이 매개변수를 지정하지 않으면 자동 재생이 비활성화됩니다. 각 슬라이드에 대해 data-swiper-autoplay 속성을 사용하여 다른 지연 시간을 지정할 수 있습니다. |
disableOnInteraction |
boolean | true | false 로 설정하면 사용자가 상호작용(스와이프)한 후에도 자동 재생이 비활성화되지 않습니다. 상호작용 후마다 자동 재생이 다시 시작됩니다. |
pauseOnMouseEnter |
boolean | false | 1. - 활성화되면 마우스 포인터가 Swiper 컨테이너에 들어갈 때 자동 재생이 일시정지됩니다. |
이 부분은 autoPlay를 설정하는 데에 쓰입니다.
- Autoplay Events
Name | Arguments | Description |
---|---|---|
autoplay |
(swiper) | 슬라이드가 자동 재생으로 변경될 때 이벤트 발생. |
autoplayPause |
(swiper) | 자동 재생이 일시정지될 때. |
autoplayResume |
(swiper) | 자동 재생이 다시 시작될 때. |
autoplayStart |
(swiper) | 자동 재생이 시작될 때. |
autoplayStop |
(swiper) | 자동 재생이 중지될 때. |
autoplayTimeLeft |
(swiper, timeLeft, progress) | 자동 재생이 활성화된 동안 지속적으로 이벤트 발생. |
슬라이더의 상태를 추적해주는 이벤트를 통해서 여러가지 핸들러와 추가적인 설정을 해줄 수 있습니다. 그 중 autoPlayTimeLeft 와 같은 이벤트는 인자를 통해 슬라이드 전환에 남은 시간(ms)을 추적하게 해주며 슬라이드 전환까지의 진행상황 비율(progress)를 넘겨주고 있습니다. 이를 통해 진행률을 확인할 수 있습니다.
(1) 기본 AutoPlay 기능 구현
<Swiper
ref={swiperRef} // Swiper 인스턴스를 swiperRef에 저장, 이 객체를 통해 각각의 Swiper 객체에 접근
loop={true} // 슬라이드를 반복하도록 설정
autoplay=
modules={[Autoplay]} // Autoplay 모듈 활성화
//이벤트 설정
onSlideChange={(swiper: SwiperCore) => { // 슬라이드가 변경될 때
setCurrentSlide(swiper.realIndex);
}}
onBeforeInit={(swiper: SwiperCore) => (swiperRef.current = swiper)} // 인스턴스가 초기화 되기 전에
onAutoplayTimeLeft={handleAutoplayTimeLeft} // Autoplay 남은 시간이 있을 때
>
...
</Swiper>
(2) Progress Bar 구현
- autoPlay의 이벤트인 onAutoplayTimeLeft의 콜백함수로 handleAutoplayTimeLeft를 만들어줍니다.
- 이 함수에서는 3개의 인자(arguments)로 swiper, timeLeft, progress를 넘겨받아 사용할 수 있습니다.
- handleAutoplayTimeLeft 함수의 역할은 현재 슬라이더의 현재 진행상태인 progress를 넘겨받아서 상태로 저장해 줍니다.
- 이때 인자로 받은 progress는 0부터 1사이의 값을 가지므로 진행률(%)로 변환하기 위해 * 100을 했습니다.
const handleAutoplayTimeLeft = (swiper: SwiperCore, timeLeft: number, progress: number) => {
//setProgress((progress) * 100);
setProgress((1 - progress) * 100);
};
- progress 의 상태를 보여주는 ui요소인 progress bar를 만들어 줍니다.
- progress 만큼의 progress Bar의 너비를 설정하면, progress Bar의 width는 0부터 100%까지 채워질 것 입니다.
<div>
<div
style=
/>
</div>
3. Swiper AutoPlay 살펴보기, Method
- Autoplay Method
Name | Description |
---|---|
swiper.pause() |
Pause autoplay (일시정지 ⏸️) |
swiper.resume() |
Resume autoplay (재개 ▶️) |
swiper.start() |
Start autoplay (자동재생 시작🔼) |
swiper.stop() |
Stop autoplay (자동재생 중지 ⏹️) |
(3) 마우스 Hover에 따라 슬라이드 정지/재생
- 먼저 Swiper를 전체를 감싸는 html dom 요소에 마우스 이벤트 핸들러를 추가해줍니다.
<div className={styles.sliderWrapper}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave} >
<Swiper>
...
</Swiper>
</div>
- AutoPlay의 네 개의 Method 중에서 pause(), resume()을 사용해서 마우스가 현재 swiper 요소에 들어왔을때는 일시정지, 요소를 벗어나면 재개되도록 하는 함수를 만들어줍니다.
const handleMouseEnter = () => {
if (swiperRef.current) {
swiperRef.current.autoplay.pause();
}
};
const handleMouseLeave = () => {
if (swiperRef.current) {
swiperRef.current.autoplay.resume();
}
};
4. start, stop vs pause, resume
여기서 왜 start(), stop() 이 아니라 pause() , resume() 을 썼는지에 궁금할 것 같습니다. 둘의 차이점을 보면 바로 이해될 것 같습니다. start() 와 stop() 를 쓰면 이 두 함수는 단순 정지와 재생의 역할을 하기 때문에 nexon 홈페이지의 progress Bar처럼 슬라이더를 멈추면 초가 초기화되고 재생시키면 0부터 다시 시작하게 됩니다. 하지만 일시정지와 재개의 기능을 하는 pause() 와 resume() 를 사용하면 초가 초기화 되지 않습니다. 멈췄다가 재개하면 남은 시간동안 진행되며 좀 더 자연스러운 progress bar를 보여줄 수 있습니다.
5. 마치며
처음엔 api 명세를 읽지 않고 start(), stop()을 쓰며 pause(), resume() 같은 기능을 구현하려고 하다보니 setInterval이며 animate며… 점점 코드가 어려워지고 산으로 갔었습니다. 처음부터 명세를 읽었더라면 삽질하는 시간을 줄였을 것 같습니다. 다음부턴 api 명세를 보고 기능을 쓰도록 해야겠다는 생각을 했습니다!