1
+ import { gsap } from 'https://cdn.skypack.dev/gsap' ;
2
+
3
+ const TRANSITION_DURATION = 0.8 ; // slide transition time in seconds
4
+ const PARALLAX_AMOUNT = 30 ; // percentage parallax overlap
5
+
6
+ class Slideshow {
7
+ constructor ( slider ) {
8
+ // Initialize DOM elements
9
+ this . slider = slider ;
10
+ this . slides = Array . from ( this . slider . querySelectorAll ( '.slide' ) ) ;
11
+ this . slidesInner = this . slides . map ( ( item ) => item . querySelector ( 'img' ) ) ;
12
+
13
+ this . current = 0 ;
14
+ this . slidesTotal = this . slides . length ;
15
+ this . isAnimating = false ;
16
+
17
+ // Set initial states
18
+ this . slides [ this . current ] . classList . add ( 'is-current' ) ;
19
+ }
20
+
21
+ navigate ( direction ) {
22
+ // Exit is an animation is already in progress
23
+ if ( this . isAnimating ) return false ;
24
+
25
+ this . isAnimating = true ;
26
+
27
+ // Save current slide index
28
+ const previous = this . current ;
29
+
30
+ // Update the current slide index based on direction
31
+ if ( direction === 1 ) {
32
+ if ( this . current < this . slidesTotal - 1 ) {
33
+ this . current += 1 ;
34
+ } else {
35
+ // If the last slide, wrap around to the first slide
36
+ this . current = 0 ;
37
+ }
38
+ } else {
39
+ if ( this . current > 0 ) {
40
+ this . current -= 1 ;
41
+ } else {
42
+ // If the first slide, wrap around to the last slide
43
+ this . current = this . slidesTotal - 1 ;
44
+ }
45
+ }
46
+
47
+ this . animate ( previous , this . current , direction ) ;
48
+ }
49
+
50
+ animate ( current , upcoming , direction ) {
51
+ const currentSlide = this . slides [ current ] ;
52
+ const currentInner = this . slidesInner [ current ] ;
53
+ const upcomingSlide = this . slides [ upcoming ] ;
54
+
55
+ gsap
56
+ . timeline ( {
57
+ defaults : {
58
+ duration : TRANSITION_DURATION ,
59
+ ease : 'power4.inOut' ,
60
+ } ,
61
+ onStart : ( ) => {
62
+ upcomingSlide . classList . add ( 'is-current' ) ;
63
+ gsap . set ( upcomingSlide , { zIndex : 1 } ) ;
64
+ } ,
65
+ onComplete : ( ) => {
66
+ currentSlide . classList . remove ( 'is-current' ) ;
67
+ gsap . set ( currentSlide , { xPercent : 0 } ) ;
68
+ gsap . set ( currentInner , { xPercent : 0 } ) ;
69
+ gsap . set ( upcomingSlide , { zIndex : 'auto' } ) ;
70
+ this . isAnimating = false ;
71
+ } ,
72
+ } )
73
+ . to ( currentSlide , {
74
+ xPercent : - direction * 100 ,
75
+ } )
76
+ . to (
77
+ currentInner ,
78
+ {
79
+ xPercent : direction * PARALLAX_AMOUNT ,
80
+ } ,
81
+ '<'
82
+ )
83
+ . fromTo (
84
+ upcomingSlide ,
85
+ {
86
+ xPercent : direction * 100 ,
87
+ } ,
88
+ {
89
+ xPercent : 0 ,
90
+ } ,
91
+ '<'
92
+ ) ;
93
+ }
94
+ }
95
+
96
+ const slider = document . querySelector ( '.slider' ) ;
97
+ const slideshow = new Slideshow ( slider ) ;
98
+
99
+ document . querySelector ( '.is-prev' ) . addEventListener ( 'click' , ( ) => slideshow . navigate ( - 1 ) ) ;
100
+ document . querySelector ( '.is-next' ) . addEventListener ( 'click' , ( ) => slideshow . navigate ( 1 ) ) ;
0 commit comments