1// Function to preload images
2function preloadImages(urls, callback) {
3 const images = urls.map((url) => {
4 const img = new Image();
5 img.onload = () => {
6 if (--images.pending === 0) {
7 callback();
8 }
9 };
10 img.src = url;
11 return img;
12 });
13 images.pending = images.length;
14}
15
16// Function to initialize the text animation
17function initTextAnimation() {
18 var staggerContainers = document.querySelectorAll(".stagger, .stagger1");
19 staggerContainers.forEach(function(container) {
20 var wordsArray = container.textContent.trim().split(/\s+/);
21
22 // Clear container
23 container.innerHTML = "";
24
25 // Append each word wrapped in a span
26 wordsArray.forEach(function(word) {
27 var span = document.createElement("span");
28 span.textContent = word + " ";
29 span.classList.add("stagger--item");
30 container.appendChild(span);
31 });
32
33 // GSAP animation for text stagger
34 gsap.to(container.querySelectorAll(".stagger--item"), {
35 scrollTrigger: {
36 trigger: container,
37 start: "top 80%",
38 end: "bottom 50%",
39 scrub: true,
40 toggleActions: "play none none none"
41 },
42 opacity: 1,
43 color: "#333",
44 duration: 1,
45 stagger: 0.1
46 });
47 });
48}
49
50// Function to initialize the image sequence animation
51function initImageSequenceAnimation() {
52 let frameCountDesktop = 239,
53 frameCountMobile = 239,
54 frameCountDesktop1 = 315,
55 frameCountMobile1 = 315,
56 desktopUrls = new Array(frameCountDesktop).fill().map((o, i) => `https://cdn.shopify.com/s/files/1/0686/4909/1296/files/1_${(i + 1).toString().padStart(5, '0')}.png`),
57 mobileUrls = new Array(frameCountMobile).fill().map((o, i) => `https://cdn.shopify.com/s/files/1/0686/4909/1296/files/1_${(i + 1).toString().padStart(5, '0')}.png`),
58 desktopUrls1 = new Array(frameCountDesktop1).fill().map((o, i) => `https://cdn.shopify.com/s/files/1/0686/4909/1296/files/Eutopia_enx_typec_asap_animation_${(i + 1).toString().padStart(5, '0')}.png`),
59 mobileUrls1 = new Array(frameCountMobile1).fill().map((o, i) => `https://cdn.shopify.com/s/files/1/0686/4909/1296/files/Eutopia_enx_typec_asap_animation_${(i + 1).toString().padStart(5, '0')}.png`);
60
61 // Preload images before initializing the animation
62 preloadImages([
63 ...desktopUrls,
64 ...mobileUrls,
65 ...desktopUrls1,
66 ...mobileUrls1
67 ], () => {
68 let canvas = document.getElementById("image-sequence"),
69 ctx = canvas.getContext("2d"),
70 images = [],
71 playhead = { frame: 0 },
72 curFrame = -1;
73
74 let canvas1 = document.getElementById("image-sequence1"),
75 ctx1 = canvas1.getContext("2d"),
76 images1 = [],
77 playhead1 = { frame1: 0 },
78 curFrame1 = -1;
79
80 let canvasSizeUpdated = false;
81 let canvasSizeUpdated1 = false;
82
83 function updateCanvasSize() {
84 if (!canvasSizeUpdated) {
85 let dpr = window.devicePixelRatio || 1;
86 canvas.width = window.innerWidth * dpr;
87 canvas.height = window.innerHeight * dpr;
88 canvas.style.width = window.innerWidth + "px";
89 canvas.style.height = window.innerHeight + "px";
90 canvasSizeUpdated = true;
91 }
92 }
93
94 function updateCanvasSize1() {
95 if (!canvasSizeUpdated1) {
96 let dpr1 = window.devicePixelRatio || 1;
97 canvas1.width = window.innerWidth * dpr1;
98 canvas1.height = window.innerHeight * dpr1;
99 canvas1.style.width = window.innerWidth + "px";
100 canvas1.style.height = window.innerHeight + "px";
101 canvasSizeUpdated1 = true;
102 }
103 }
104
105 function updateImage() {
106 let frame = Math.round(playhead.frame);
107 if (frame !== curFrame) {
108 ctx.clearRect(0, 0, canvas.width, canvas.height);
109 ctx.drawImage(images[frame], 0, 0, canvas.width, canvas.height);
110 curFrame = frame;
111 }
112 }
113
114 function updateImage1() {
115 let frame1 = Math.round(playhead1.frame1);
116 if (frame1 !== curFrame1) {
117 ctx1.clearRect(0, 0, canvas1.width, canvas1.height);
118 ctx1.drawImage(images1[frame1], 0, 0, canvas1.width, canvas1.height);
119 curFrame1 = frame1;
120 }
121 }
122
123 function imageSequence(config) {
124 updateCanvasSize();
125
126 window.addEventListener("resize", function() {
127 updateCanvasSize();
128 });
129
130 let urls = config.isMobile ? mobileUrls : desktopUrls;
131
132 images = urls.map((url, i) => {
133 let img = new Image();
134 img.src = url;
135 i || (img.onload = updateImage);
136 return img;
137 });
138
139 canvas.addEventListener('touchstart', function() {
140 gsap.set(playhead, { paused: true });
141 });
142
143 canvas.addEventListener('touchend', function() {
144 gsap.set(playhead, { paused: false });
145 });
146
147 gsap.to(playhead, {
148 frame: images.length - 1,
149 ease: "none",
150 onUpdate: updateImage,
151 duration: images.length / (config.fps || 60),
152 paused: !!config.paused,
153 scrollTrigger: config.scrollTrigger
154 });
155 }
156
157 function imageSequence1(config) {
158 updateCanvasSize1();
159
160 window.addEventListener("resize", function() {
161 updateCanvasSize1();
162 });
163
164 let urls1 = config.isMobile ? mobileUrls1 : desktopUrls1;
165
166 images1 = urls1.map((url1, i) => {
167 let img1 = new Image();
168 img1.src = url1;
169 i || (img1.onload = updateImage1);
170 return img1;
171 });
172
173 canvas1.addEventListener('touchstart', function() {
174 gsap.set(playhead1, { paused: true });
175 });
176
177 canvas1.addEventListener('touchend', function() {
178 gsap.set(playhead1, { paused: false });
179 });
180
181 gsap.to(playhead1, {
182 frame1: images1.length - 1,
183 ease: "none",
184 onUpdate: updateImage1,
185 duration: images1.length / (config.fps || 60),
186 paused: !!config.paused,
187 scrollTrigger: config.scrollTrigger
188 });
189 }
190
191 imageSequence({
192 isMobile: /Mobi|Android/i.test(navigator.userAgent),
193 canvas: "#image-sequence",
194 scrollTrigger: {
195 trigger: "#animation-section",
196 start: "center center",
197 end: "+=200%",
198 scrub: true,
199 pin: true
200 },
201 fps: 60,
202 paused: true
203 });
204
205 imageSequence1({
206 isMobile: /Mobi|Android/i.test(navigator.userAgent),
207 canvas: "#image-sequence1",
208 scrollTrigger: {
209 trigger: "#animation-section1",
210 start: "center center",
211 end: "+=200%",
212 scrub: true,
213 pin: true
214 },
215 fps: 60,
216 paused: true
217 });
218
219 initTextAnimation(); // Call text animation initialization after image sequence setup
220 });
221}
222
223
224
225
226
227
228
229// Call the initialization functions after DOM content is fully loaded
230document.addEventListener("DOMContentLoaded", function() {
231 initImageSequenceAnimation();
232});