플러그인/swiper

swiper 무한슬라이드와 버튼 fade효과

찐망고 2024. 9. 12. 16:22

 

안녕하세요 찐망고입니다.

저번 포스팅엔 기본슬라이드에서 버튼을 눌렀을 때 fade효과가 나오는 슬라이드를 만들어 보았는데요

 

swiper effect) fade와 slide동시에 구현하기

안녕하세요 찐망고입니다.오래간만에 swiper 관련 포스팅을 하네요.생각보다 고민을 많이 한 코드라 공유하고자 같이 포스팅해봅니다  클론 한 사이트는 노보셀바이오입니다.http://novocellbio.com/

uiweb.tistory.com

 

무한슬라이드는 

loop의 형태를 false에서 true로 변경해 주면 됩니다.

 

슬라이드가 loop형태로 바뀌면 슬라이드가 무한 반복되도록 복제된 슬라이드가 추가되어, 

실제슬라이더의 인덱스 위치가 바뀌므로

realIndex대신 activeIndex를 사용해야 합니다.

 

그렇다고 이전 코드에서 저 문구만 바꾸면 에러 메시지가 뜨는데

techSwiper가 선언되기 전에 접근하기 때문이죠.

 

그래서 swiper를 먼저 선언하고 techSwiper.on('slideChange')를 이용하여 이벤트로 지정하고

탭버튼을 눌렀을 때의 index 위치를 맞춰주기 위해 

아래 두 코드를 수정해 줍니다.

// 루프된 슬라이드와 일치하는 실제 슬라이드의 인덱스 가져오기
  const targetSlideIndex = Array.from(document.querySelectorAll('.tech-slider .swiper-slide'))
    .find(slide => slide.getAttribute('data-swiper-slide-index') == index)
    .getAttribute('data-swiper-slide-index');
    
// 100ms 후에 해당 슬라이드를 변경하고 fade-in 처리
  setTimeout(() => {
    techSwiper.slideToLoop(targetSlideIndex, 0);  // 무한 슬라이드를 위한 slideToLoop 사용
    const nextSlide = document.querySelector('.tech-slider .swiper-slide[data-swiper-slide-index="' + targetSlideIndex + '"]');
    nextSlide.classList.add('fade-in');

 

 

추가적으로 수정해 본 코드는 setTimeout인데

너무 짧은 시간에 여러 번 호출하는 것보다 한 번의 애니메이션 루프에서

여러 작업을 동시에 처리하는 방식으로 최적화하는 게 좋을 것 같아 requestAnimationFrame으로 코드를 수정해 봅니다.

 

이전 코드는 CSS애니메이션과 별개로 동작해서 슬라이드가 이동하기 전 또는 후에 시간을 지연시키는 역할만 했는데요.

이 방법은 애니메이션 완료타이밍을 CSS에서 관리하므로 setTimeout을 사용할 필요가 없죠.

// 현재 슬라이드에 fade-out 애니메이션 적용
currentSlide.classList.add('fade-out');

// 애니메이션 완료 후 클래스 제거 (fade-out 끝나면 이벤트 발생)
currentSlide.addEventListener('animationend', function handleFadeOut() {
    currentSlide.classList.remove('fade-out');
    currentSlide.removeEventListener('animationend', handleFadeOut);  // 이벤트 리스너 제거
});

// requestAnimationFrame을 사용해 슬라이드를 최적화된 방식으로 이동
requestAnimationFrame(() => {
    techSwiper.slideToLoop(targetSlideIndex, 0);  // 슬라이드 이동

    // 다음 슬라이드에 fade-in 애니메이션 적용
    const nextSlide = document.querySelector('.tech-slider .swiper-slide[data-swiper-slide-index="' + targetSlideIndex + '"]');
    nextSlide.classList.add('fade-in');

    // 애니메이션 완료 후 클래스 제거 (fade-in 끝나면 이벤트 발생)
    nextSlide.addEventListener('animationend', function handleFadeIn() {
        nextSlide.classList.remove('fade-in');
        nextSlide.removeEventListener('animationend', handleFadeIn);  // 이벤트 리스너 제거
    });
});
}

 

 

 

전체코드

 // 탭 슬라이더 설정
const tabSwiper = new Swiper('.tab-slider', {
    slidesPerView: 'auto',  // 탭 슬라이더 자동 크기 설정
});


// 콘텐츠 슬라이더 설정을 먼저 선언해서 참조 에러 방지
let techSwiper = new Swiper('.tech-slider', {
    loop: true,  // loop 기능 활성화
    effect: 'slide',  // fade 효과 사용
});

// fade 효과를 위한 CSS 클래스 추가 및 제거
function fadeInOutContent(index) {
    const currentSlide = document.querySelector('.tech-slider .swiper-slide-active');


    // 루프된 슬라이드와 일치하는 실제 슬라이드의 인덱스 가져오기
    const targetSlideIndex = Array.from(document.querySelectorAll('.tech-slider .swiper-slide'))
        .find(slide => slide.getAttribute('data-swiper-slide-index') == index)
        .getAttribute('data-swiper-slide-index');


    // 현재 슬라이드에 fade-out 애니메이션 적용
    currentSlide.classList.add('fade-out');

    // 애니메이션 완료 후 클래스 제거 (fade-out 끝나면 이벤트 발생)
    currentSlide.addEventListener('animationend', function handleFadeOut() {
        currentSlide.classList.remove('fade-out');
        currentSlide.removeEventListener('animationend', handleFadeOut);  // 이벤트 리스너 제거
    });

    // requestAnimationFrame을 사용해 슬라이드를 최적화된 방식으로 이동
    requestAnimationFrame(() => {
        techSwiper.slideToLoop(targetSlideIndex, 0);  // 슬라이드 이동

        // 다음 슬라이드에 fade-in 애니메이션 적용
        const nextSlide = document.querySelector('.tech-slider .swiper-slide[data-swiper-slide-index="' + targetSlideIndex + '"]');
        nextSlide.classList.add('fade-in');

        // 애니메이션 완료 후 클래스 제거 (fade-in 끝나면 이벤트 발생)
        nextSlide.addEventListener('animationend', function handleFadeIn() {
            nextSlide.classList.remove('fade-in');
            nextSlide.removeEventListener('animationend', handleFadeIn);  // 이벤트 리스너 제거
        });
    });
}


// 슬라이더 초기화가 완료된 후에 slideChange 이벤트 설정
techSwiper.on('slideChange', function () {
    const activeIndex = techSwiper.realIndex;  // loop에서는 realIndex 사용
    document.querySelectorAll('.tab-btn').forEach((tab, index) => {
        if (index === activeIndex) {
            tab.classList.add('active');
        } else {
            tab.classList.remove('active');
        }
    });
});

// 탭 클릭 시 fade 효과 적용
document.querySelectorAll('.tab-btn').forEach((tab, index) => {
    tab.addEventListener('click', function () {
        // 현재 활성화된 버튼과 동일한 버튼을 클릭한 경우에는 fade 처리하지 않음
        if (!tab.classList.contains('active')) {
            fadeInOutContent(index);  // 탭 클릭 시 fade 효과 적용
        }
    });
});

 

 

 

아래 코드펜에서 확인해 보세요~

 

See the Pen swiper무한슬라이드와fade버튼 by 찐망고 (@nnwbliyz-the-styleful) on CodePen.