[JavaScript] Swiper 해상도에 따라 다른 효과 사용하기 (반응형)
Lpla
·2022. 1. 3. 21:23
Swiper를 PC 해상도에서만 사용하거나 모바일 해상도에서만 사용하는 기능을 원하면 다음 포스팅을 참고하자.
코딩을 하다보면 다양한 요구사항에 맞닥뜨린다.
이번에는 1200px 이상의 해상도에서는 슬라이드,
1200px 미만의 해상도에서는 페이드인 Swiper 슬라이드를 만들고자 한다.
1. breakpoints?
swiper의 breakpoints는 해상도에 따라 슬라이드 개수, 슬라이드 간격 등을 조절할 수 있지만
반복 여부나 효과 등 세부 기능들은 지원하지 않는다고 공식 문서에서 설명하고 있다.
따라서 이 방법으로 해결이 불가능하다.
2. 리팩토링을 생각하지 않는다면...
코드를 깔끔하게 정리하여 가독성과 실제 성능을 높이는 작업을 리팩토링이라고 한다.
사실 리팩토링을 생각하지 않는다면 생각보다 쉽게 문제를 해결할 수 있다.
기본 구조는 아래처럼 짰다.
HTML
<div class="swiper-container mySwiper">
<div class="swiper-wrapper">
<div class="swiper-slide slide01"></div>
<div class="swiper-slide slide02"></div>
<div class="swiper-slide slide03"></div>
<div class="swiper-slide slide04"></div>
<div class="swiper-slide slide05"></div>
<div class="swiper-slide slide06"></div>
<div class="swiper-slide slide07"></div>
<div class="swiper-slide slide08"></div>
<div class="swiper-slide slide09"></div>
<div class="swiper-slide slide10"></div>
</div>
</div>
CSS
.swiper-container { padding-bottom: 30px; }
.swiper-slide { width: 20%; height: 200px; box-shadow: 0 2px 10px 0px #848484; margin-top: 30px; }
.swiper-slide.slide01 { background-color: #BE5EC2; }
.swiper-slide.slide02 { background-color: #F862A7; }
.swiper-slide.slide03 { background-color: #FF7B87; }
.swiper-slide.slide04 { background-color: #FFA26A; }
.swiper-slide.slide05 { background-color: #FFCE5E; }
.swiper-slide.slide06 { background-color: #F9F871; }
.swiper-slide.slide07 { background-color: #9BDE7E; }
.swiper-slide.slide08 { background-color: #4BBC8E; }
.swiper-slide.slide09 { background-color: #039590; }
.swiper-slide.slide10 { background-color: #1C6E7D; }
2-1. swiper 초기화
이제 자바스크립트를 작성할 차례다.
한 번에 원하는 코드를 모두 작성하는 것은 어려우니 차근차근 해보자.
1200px 이상에서는 effect: 'slide' 인 swiper를 실행해야 한다.
let swiper = new Swiper('.swiper-container', {
loop: true,
spaceBetween: 10,
slidesPerView: 5,
autoplay: {
delay: 1000,
disableOnInteraction: false,
},
effect: 'slide'
});
그리고 1200px 미만에서는 effect: 'fade' 인 swiper를 실행해야 한다.
swiper = new Swiper('.swiper-container', {
loop: true,
spaceBetween: 10,
slidesPerView: 5,
autoplay: {
delay: 1000,
disableOnInteraction: false,
},
effect: 'fade'
});
둘의 차이는 effect 값 밖에 없다.
2-2. 반응형
이 두 종류의 swiper가 브라우저의 해상도에 따라 각각 실행되면 된다.
브라우저의 해상도를 구하는 방법에는 몇 가지가 있는데 여기서는 window.innerWidth를 사용했다.
let ww = window.innerWidth;
responsiveSwiper();
function responsiveSwiper() {
if (ww >= 1200) {
// 슬라이드 효과
} else if (ww < 1200) {
// 페이드 효과
}
}
브라우저의 해상도를 ww 변수에 할당했다.
그리고 해상도가 바뀌면 ww 값도 새로 변경해줘야 하고
변경한 ww 값에 맞춰서 다시 알맞은 swiper를 실행해야 한다.
브라우저의 크기가 변경될 때 이벤트가 발생하는 addEventListener('resize') 를 사용한다.
let ww = window.innerWidth;
window.addEventListener('resize', function() {
ww = window.innerWidth;
responsiveSwiper();
});
이제 위에서 작성한 네 가지 코드들을 하나로 합치면 된다.
let ww = window.innerWidth;
let swiper = new Swiper('.swiper-container', {
loop: true,
spaceBetween: 10,
slidesPerView: 5,
autoplay: {
delay: 1000,
disableOnInteraction: false,
},
effect: 'slide',
});
responsiveSwiper();
function responsiveSwiper() {
if (ww >= 1200) {
// 슬라이드 효과
swiper = new Swiper('.swiper-container', {
loop: true,
spaceBetween: 10,
slidesPerView: 5,
autoplay: {
delay: 1000,
disableOnInteraction: false,
},
effect: 'slide',
});
} else if (ww < 1200) {
// 페이드 효과
swiper = new Swiper('.swiper-container', {
loop: true,
spaceBetween: 10,
slidesPerView: 5,
autoplay: {
delay: 1000,
disableOnInteraction: false,
},
effect: 'fade'
});
}
}
window.addEventListener('resize', function() {
ww = window.innerWidth;
responsiveSwiper();
});
2-3. swiper 제거
같은 코드가 여러번 중복되는 것은 둘째치더라도 이 코드는 에러가 있다.
해상도가 변경될 때마다 resize 이벤트에 의해 새로운 swiper가 실행되는데 그것이 중복되어 실행된다.
해상도가 1600px일 때 swiper가 실행되고, 1590px일 때도 swiper가 실행되는데
이 두개가 같이 작동하여 충돌을 일으킨다.
그 결과 대환장파티가 벌어진다.
이것을 방지하기 위해 swiper.destroy()로 기존 swiper를 제거하고 새로운 swiper를 실행해야 한다.
그 코드는 아래와 같다.
See the Pen Swiper effect 반응형 - 리팩토링 전 by lpla (@lpla) on CodePen.
이 코드는 깔끔하지 않더라도 우리가 원하는 기능이 모두 있다.
실무라면 제대로 작동하는 코드를 빠르게 만들어서 바로 적용하는 것이 좋을 수 있다.
하지만 지금은 공부하는 차원에서 리펙토링을 해보겠다.
3. 중복 삭제
앞선 코드에서 swiper는 총 세 번 중복된다.
그렇다면 이것을 하나로 합치는 것이 최우선 과제다.
initSwiper('slide');
function initSwiper(effect) {
let swiper = new Swiper('.swiper-container', {
loop: true,
spaceBetween: 10,
slidesPerView: 5,
autoplay: {
delay: 1000,
disableOnInteraction: false,
},
effect: effect
});
}
이 코드를 실행하면 initSwiper의 인수로 'slide'를 전달하여 effect: 'slide'인 swiper가 실행된다.
initSwiper('fade'); 를 사용하면 effect: 'fade'인 swiper가 실행된다.
함수를 만들어 코드 중복을 해결할 수 있는 것이다.
2번에서 완성한 코드 중 일부를 함수로 수정해보자.
let ww = window.innerWidth;
responsiveSwiper();
function initSwiper(effect) {
let swiper = new Swiper('.swiper-container', {
loop: true,
spaceBetween: 10,
slidesPerView: 5,
autoplay: {
delay: 1000,
disableOnInteraction: false,
},
effect: effect
});
}
function responsiveSwiper() {
if (ww >= 1200) {
// 슬라이드 효과
swiper.destroy();
initSwiper('slide');
} else if (ww < 1200) {
// 페이드 효과
swiper.destroy();
initSwiper('fade');
}
}
window.addEventListener('resize', function() {
ww = window.innerWidth;
responsiveSwiper();
});
하지만 코드를 실행하면 swiper가 정의되지 않았다는 에러가 뜬다.
당연하게도 swiper는 initSwiper() 함수 안에 정의되어 있고 이것은 지역 스코프로써
initSwiper() 함수 외부에서는 swiper에 접근할 수 없기 때문에 발생하는 에러다.
swiper를 여러번 재사용하기 위해 함수로 정의했는데 그렇게 하면 외부에서 접근을 할 수 없다.
initSwiper() 함수 내부에서 swiper를 제거하도록 위치를 옮겨 보았다.
이 역시 swiper를 초기화 하기 전에 먼저 swiper.destroy()를 사용해서 에러가 발생했다.
그렇다면 처음부터 빈 swiper 변수를 선언해두면 어떨까?
변수를 미리 선언하더라도 아직 swiper를 초기화하지 않은 것은 마찬가지이므로 에러가 발생한다.
swiper를 실행(초기화)하면 swiper의 타입은 object다.
따라서 타입이 object라면 swiper가 실행 중이라는 의미이고 swiper.destroy()로 제거가 가능하다.
타입이 object가 아니라면 swiper가 실행되고 있지 않다는 의미이고 destroy()를 사용할 수 없다.
따라서 타입을 확인할 수 있는 typeof 연산자로
typeof(swiper) == 'object' 일 때 제거하도록 구문을 바꿔보자.
드디어 에러가 발생하지 않는다.
See the Pen Swiper effect 반응형 - 리팩토링 완성 by lpla (@lpla) on CodePen.