// Slider class definition for managing a slideshow export class Slider { DOM = { el: null }; // Define a private property to store the current slide index #current = 0; // Constructor accepts a DOM element representing the slider constructor(DOM_el) { this.DOM.el = DOM_el; gsap.set(this.DOM.el, {perspective: 500}); // Create an array of all slides this.slides = [...this.DOM.el.querySelectorAll('.slider__item')]; // Calculate the total number of slides this.slidesTotal = this.slides.length; // Set the current slide's class to 'slider__item--current' this.slides[this.current].classList.add('slider__item--current'); // Set the previous slide's class to 'slider__item--previous' this.slides[this.getPreviousPosition()].classList.add('slider__item--previous'); } // Method to get the index of the previous slide getPreviousPosition() { return this.current != 0 ? this.current - 1 : this.slidesTotal - 1; } // Method to get the index of the slide before the previous slide getPreviousPreviousPosition() { const position = this.getPreviousPosition(); return position != 0 ? position-1 : this.slidesTotal - 1; } // Method to get the index of the next slide getNextPosition() { return this.current != this.slidesTotal - 1 ? this.current + 1 : 0; } // Method to navigate to the next slide next() { this.navigate(1); } // Method to navigate to the previous slide prev() { this.navigate(0); } // Getter for the current slide index get current() { return this.#current; } // Setter for the current slide index set current(value) { this.#current = value; } // Method to navigate the slider in the given direction (1 for next, 0 for previous) navigate(direction) { // Return early if an animation is in progress if ( this.isAnimating ) return false; this.isAnimating = true; // Define variables to reference the current, next, previous, and slide before previous slide const currentSlide = this.slides[this.current]; const nextSlide = this.slides[this.getNextPosition()]; const previousSlide = this.slides[this.getPreviousPosition()]; const previousPreviousSlide = this.slides[this.getPreviousPreviousPosition()]; // Next slide's inner image const nextSlideInner = nextSlide.querySelector('.slider__item-inner') // Animate the slider navigation using GSAP const tl = gsap.timeline({ defaults: { duration: 1, ease: 'power4.inOut' }, onStart: () => { if ( !direction ) { gsap.set(previousPreviousSlide, {opacity: 1, scale: 1}); } // Set z-indexes for proper layering const incomingSlide = direction ? nextSlide : previousSlide; // Reset slides z-indexes and rotations gsap.set(this.slides, {zIndex: 0, rotationX: 0, willChange: 'transform, opacity'}); gsap.set(incomingSlide, {zIndex: direction ? 3 : 2}); gsap.set(currentSlide, {zIndex: direction ? 2 : 3}); gsap.set(direction ? previousSlide : previousPreviousSlide, {zIndex: 1}); }, onComplete: () => { // Update classes for current and previous slides based on direction currentSlide.classList.remove('slider__item--current'); previousSlide.classList.remove('slider__item--previous'); (direction ? nextSlide : previousSlide).classList.add('slider__item--current'); (direction ? currentSlide : previousPreviousSlide).classList.add('slider__item--previous'); // Set the isAnimating property to false, indicating that the animation is complete this.isAnimating = false; } }) .to(currentSlide, { scale: direction, rotationX: () => !direction ? -90 : 0 }) .fromTo(direction ? nextSlide : previousSlide, { scale: direction ? 0 : 1, rotationX: () => direction ? -90 : 0, opacity: 1, }, { duration: 0.8, ease: 'expo', scale: 0.3, rotationX: 0 }, 0.5) // Animate the inner image too if direction is 'next' if ( direction ) { tl.fromTo(nextSlideInner, { scale: 2 }, { duration: 0.8, ease: 'expo', scale: 1, }, 0.5) } // Update the current slide index based on the navigation direction this.current = direction ? this.getNextPosition() : this.getPreviousPosition(); } }