[Swiper.js] display:none에서 block으로 바꿨을 시 autoplay 이슈 해결

김방울·2023년 2월 6일
1

JavaScript

목록 보기
4/7

💬 swiper.js 8.4.7 버전을 기준으로 작성하였습니다.

React.js를 사용하지 않고 그림과 같이 탭 메뉴로 구성된 컨텐츠를 마크업하게 될 경우, 일반적으로 보이지 않는 탭 메뉴를 display: none 처리하여 사용하는 경우가 많을 것입니다.👀

이번에 TypeScript + Swiper.js를 이용하여 위 구조를 만들게 되었는데, swiper 기능은 작동하는데 autoplay(자동 재생)만 되지 않는 이슈가 있었습니다.

  // PARAM swiper option
  // 공통적으로 사용되는 슬라이드 옵션을 만들었습니다.
  const swiperOption: SO = {
    speed: 400,
    loop: true,
    init: true,
    effect: 'slide',
    autoHeight: true,
  };
  // FUNCTION swiper init
  const swiper = new Swiper('.slide', {
    // rest 문법으로 공통으로 사용되는 슬라이드 옵션을 새로 정의할 옵션과 합쳐주었습니다.
    ...swiperOption,
    speed: 700,
    autoplay: {
      delay: 3500,
      disableOnInteraction: false,
    },
    spaceBetween: 20,
    centeredSlides: true,
    slidesPerView: 1,
    navigation: {
      prevEl: document.querySelector('.slide .swiper-button-prev'),
      nextEl: document.querySelector('.slide .swiper-button-next'),
    },
    pagination: {
      el: '.swiper-pagination',
      clickable: true,
    },
    breakpoints: {
      641: {
        slidesPerView: 'auto',
      },
    },
  });

swiper 객체 옵션 속성은 다음과 같았습니다. autoplay 속성을 설정해 주었는데도 자동 재생만 작동되지 않았습니다.

검색을 해 보니, display:none 일 시에는 swiper.js의 autoplay가 제대로 작동하지 않는다고 합니다. (width 계산 문제로 autoplay 작동이 멈추는 것으로 추정됩니다🤔)

observer 속성과 observeParents 속성을 추가하면 Swiper 요소나 부모 요소의 DOM 변경이 감지되었을 경우, Swiper를 자동으로 업데이트(재초기화) 해 준다고 하여 다음 옵션을 추가하였습니다.

  const swiperOption: SO = {
    observer: true,
    observeParents: true,
    speed: 400,
    loop: true,
    init: true,
    effect: 'slide',
    autoHeight: true,
  };

그런데도 자동 재생이 실행되지 않았습니다. 분명 글들에는 전부 다 해당 옵션들을 추가하면 해결된다고 쓰여 있었는데...😇

그래서 슬라이드 강제 업데이트를 실행해 주었습니다.

// FUNCTION swiper restart
const setSwiperStart = (swiper: Swiper) => {
  const tab = document.querySelector('.contents--story');
  
  if (tab?.classList.contains('active')) {
    swiper.update();
  } 
};

swiper 객체를 매개변수로 받아 슬라이드가 있는 해당 탭 요소에 active 라는 클래스(display: block 으로 설정해 주는 클래스) 가 있을 경우 업데이트 해 주는 함수를 만들었습니다.

  tabList.forEach((el) => {
    el.addEventListener('click', onClickTabBtn);
    el.addEventListener('click', () => setSwiperStart(swiper));   
  });
  sidebarMenu.forEach((el) => {
    el.addEventListener('click', onClickTabBtn);
    el.addEventListener('click', () => setSwiperStart(swiper));
  });

그리고 탭 메뉴를 전환하는 버튼을 클릭했을 시, 해당 함수를 실행하도록 addEventListner 로 추가해 주었습니다. (지금 보니까.. onClickTabBtn 안에서 호출하는 게 더 깔끔했을 것 같네요😹)

그리고 결과는... 실행되지 않았습니다 💀

뭔가 이상해 함수에console.log(swiper.autoplay); 를 추가해주니 콘솔창에 다음과 같은 Object가 출력되었습니다.

속성명을 보니 왠지 pausedrunning이 동작 상태 같고,
stopstart는 상태를 전환해 주는 메서드 인 것 같습니다. 그리고 runningfalse 상태네요.

그래서 함수를 다음과 같이 수정해 주었습니다.

// FUNCTION swiper restart
const setSwiperStart = (swiper: Swiper) => {
  const tab = document.querySelector('.contents--story');
  if (tab?.classList.contains('active')) {
    swiper.autoplay.start(); // 추가!
    swiper.update();
  } else {
    swiper.autoplay.pause(); // 추가!
    swiper.update();
  }
  console.log(swiper.autoplay);
};

그런데 이렇게 해도 실행되지 않았습니다.
속성 값을 직접 바꾸는 방법으로 다시 한번 함수를 수정해 주었습니다.

const setSwiperStart = (swiper: Swiper) => {
  const tab = document.querySelector('.contents--story');
  if (tab?.classList.contains('active')) {
    swiper.autoplay.paused = false;
    swiper.autoplay.running = true;
  } else {
    swiper.autoplay.paused = true;
  }
  console.log(swiper.autoplay);
};

running 속성의 값이 true로 바뀌고 드디어 자동 재생이 되기 시작합니다.😂
observerobserveParents 속성을 true로 적용하였는데도 자동 재생이 실행되지 않을 경우, 위와 같은 방법들을 사용해 보는 것도 해결책이 될 수 있을 것 같습니다.

profile
코딩하는 고양이🐱 / UI Developer, Front-end Developer

0개의 댓글