-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmain.js
More file actions
761 lines (658 loc) · 33 KB
/
main.js
File metadata and controls
761 lines (658 loc) · 33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
/*
=================================
Table of Contents
=================================
=================================
Universal Stuff
=================================
1. Global variables
2. Dynamic scroll indicator at bottom of screen
3. Smooth scrolling to sections on button and link click/tap
==================================
Mobile Design
==================================
4. Mobile design navigation menu
5. Mobile events section animations
==================================
Desktop Design
==================================
6. Navigation bar color transition
7. Mission card description on hover
8. E-board picture and description carousel
9. Events tooltip show on click
10. Parallax scrolling effects
*/
// wait until the document is fully loaded to load the javascript code
$(document).ready(function() {
/*
---------------------
1. Global variables
---------------------
*/
// website sections
const navbar = document.querySelector('nav');
const homepage = document.querySelector('header');
const about = document.querySelector('#about');
const mission = document.querySelector('#mission');
const eboard = document.querySelector('#e-board');
const projects = document.querySelector('#projects');
const contactUs = document.querySelector('#contact-us');
// get dimensions of user's viewport
const viewportHeight = document.documentElement.clientHeight;
const viewportWidth = document.documentElement.clientWidth;
// desktop media query
let desktop = window.matchMedia('(min-width: 768px)');
// large desktop resolution media query
// about section elements
// these need to be declared here to prevent the elements inside the section clipping on mobile design
const aboutTitle = document.querySelector('.about-title');
const typingComputer = document.querySelector('.about-computer');
const aboutDesc = document.querySelector('.about-desc-wrapper');
/*
-------------------------------------------------
2. Dynamic scroll indicator at bottom of screen
-------------------------------------------------
*/
// scroll indicator at bottom of screen
const scrollIndicatorText = document.querySelector('.scroll-indicator');
const scrollIndicatorArrow = document.querySelector('.arrow');
// separate options for home page so scroll indicator changes to white when 90% of the homepage is on screen
const homeIndicatorOptions = {
threshold: 0.90
};
const homeIndicator = new IntersectionObserver((entries, homeIndicator) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// change color of scroll indicator and link to about section
scrollIndicatorText.style.color = 'white';
scrollIndicatorArrow.style.borderColor = 'white';
scrollIndicatorArrow.href = '#about';
}
});
}, homeIndicatorOptions);
homeIndicator.observe(homepage);
/* separate options for all other sections so scroll indicator is observed when at least 1% of the corresponding section is
on screen */
const sectionOptions = {
threshold: [0.01, 0.25, 0.5, 0.75, 1.0]
};
const scrollIndicator = new IntersectionObserver((entries, scrollIndicator) => {
entries.forEach(entry => {
// First, check if the user is on a desktop window size or mobile
if (desktop.matches) {
// user is on desktop
if (entry.isIntersecting) {
// Figure out what section is currently being observed
switch (entry.target.id) {
case 'about':
// change color of scroll indicator and link to the next section
scrollIndicatorText.style.color = 'black';
scrollIndicatorArrow.style.borderColor = 'black';
scrollIndicatorArrow.href = '#mission';
break;
case 'mission':
scrollIndicatorText.style.color = 'black';
scrollIndicatorArrow.style.borderColor = 'black';
scrollIndicatorArrow.href = '#e-board';
break;
case 'events':
scrollIndicatorArrow.href = '#projects';
break;
case 'projects':
scrollIndicatorArrow.href = '#contact-us';
break;
}
}
}
else {
// user is on mobile
if (entry.isIntersecting) {
// Figure out what section is currently being observed
switch (entry.target.id) {
case 'about':
// change color of scroll indicator and link to the next section
scrollIndicatorText.style.color = 'black';
scrollIndicatorArrow.style.borderColor = 'black';
scrollIndicatorArrow.href = '#mission';
break;
case 'mission':
scrollIndicatorText.style.color = 'black';
scrollIndicatorArrow.style.borderColor = 'black';
scrollIndicatorArrow.href = '#e-board';
break;
case 'e-board':
scrollIndicatorText.style.color = 'black';
scrollIndicatorArrow.style.borderColor = 'black';
scrollIndicatorArrow.href = '#events';
break;
case 'events':
scrollIndicatorText.style.color = 'black';
scrollIndicatorArrow.style.borderColor = 'black';
scrollIndicatorArrow.href = '#projects';
break;
case 'projects':
scrollIndicatorText.style.color = 'black';
scrollIndicatorArrow.style.borderColor = 'black';
scrollIndicatorArrow.href = '#contact-us';
break;
}
}
}
});
}, sectionOptions);
// separate options and observer for e-board section for different behavior when scrolling up or down
const eBoardOptions = {
threshold: [0.1, 0.2, 0.4, 0.6, 0.8, 1.0]
};
// variable to compare currentY to determine scroll direction
let previousRatio = 0;
const eboardObserver = new IntersectionObserver((entries, eBoardObserver) => {
entries.forEach(entry => {
let previousY = 0;
const currentY = entry.boundingClientRect.y;
const currentRatio = entry.intersectionRatio;
// different behavior on desktop
if (entry.isIntersecting) {
// scrolling up
if (currentY < previousY) {
scrollIndicatorText.style.color = 'white';
scrollIndicatorArrow.style.borderColor = 'white';
}
// scrolling down
else if (currentY > previousY && entry.isIntersecting) {
scrollIndicatorText.style.color = 'black';
scrollIndicatorArrow.style.borderColor = 'black';
scrollIndicatorArrow.href = '#events';
}
}
});
}, eBoardOptions);
// separate options and observer for website footer because of different behavior
const footerOptions = {
threshold: 0.01
};
const footerObserver = new IntersectionObserver((entries, footerObserver) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
scrollIndicatorText.style.opacity = '0';
scrollIndicatorArrow.style.opacity = '0';
}
else {
scrollIndicatorText.style.opacity = '1';
scrollIndicatorArrow.style.opacity = '1';
}
});
}, footerOptions);
// call intersection observer for each section of the website to update scroll indicator at bottom of screen
scrollIndicator.observe(about);
scrollIndicator.observe(mission);
// call different intersection observer for desktop and mobile because of different behavior
if (desktop.matches) {
eboardObserver.observe(eboard);
}
else {
scrollIndicator.observe(eboard);
}
scrollIndicator.observe(events);
scrollIndicator.observe(projects);
footerObserver.observe(contactUs);
/*
--------------------------------------------------------------
3. Smooth scrolling to sections on button and link click/tap
--------------------------------------------------------------
*/
const scrollButton = $('.smoothScroll');
let $root = $('body, html');
// smooth scroll only on desktop
if (desktop.matches) {
scrollButton.click(function(event) {
event.preventDefault();
$root.animate({
scrollTop: $(this.hash).offset().top
// how much time it takes to smooth scroll in milliseconds
}, 2500);
});
}
/*
==================================
Mobile Design
==================================
*/
/*
----------------------------------
4. Mobile design navigation menu
----------------------------------
*/
const hamburgerMenuContainer = document.querySelector('.hamburger-menu-container');
const navbarContainer = document.querySelector('.navbar-container');
const hamburgerExitBttn = document.querySelector('.navigation-menu-exit-wrapper');
const navbarLinks = document.querySelectorAll('.navbar-link');
// open the hamburger navigation menu
hamburgerMenuContainer.addEventListener('touchend', event => {
event.preventDefault();
navbarContainer.classList.add('navbar-container-active');
});
// exit the hamburger navigation menu after tapping exit button or clicking a navigation link
hamburgerExitBttn.addEventListener('touchend', event => {
event.preventDefault();
navbarContainer.classList.remove('navbar-container-active');
});
navbarLinks.forEach(navbarLink => {
navbarLink.addEventListener('touchend', event => {
// check if mobile navigation link currently being tapped is "about" section
if (navbarLink.href == 'http://127.0.0.1:5500/#about') {
aboutTitle.style.transform = 'translateY(0px)';
aboutDesc.style.transform = 'translateY(0px)';
typingComputer.style.transform = 'translateY(0px)';
console.log('fired');
}
navbarContainer.classList.remove('navbar-container-active');
});
});
/*
-------------------------------------
5. Mobile events section animations
-------------------------------------
*/
// all the mobile event descriptions
const eventDescs = document.querySelectorAll('.mobile-events-desc-container');
const mobileCSSPI = document.querySelector('#mobile-csspi');
const mobileWebDesign = document.querySelector('#mobile-web-design');
const mobileSpeaker = document.querySelector('#mobile-speaker');
const mobileRecruiter = document.querySelector('#mobile-recruiter');
const mobileWorkshops = document.querySelector('#mobile-workshops');
// mobile events background that displays when button is tapped and all the mobile events section buttons
const mobileEventsBackground = document.querySelector('.events-mobile-background');
const mobileEventsButtons = document.querySelectorAll('.mobile-events-button-container');
// different colors to choose from for mobile events background when clicking on events
const recruiterColor = 'rgba(103, 121, 255, 0.8)';
const csspiColor = 'rgba(244, 143, 143, 0.8)';
const speakerColor = 'rgba(40, 240, 140, 0.8)';
const workshopsColor = 'rgba(255, 177, 77, 0.8)';
const webDesignColor = 'rgba(167, 0, 255, 0.8)';
// initialize variable now to set active container later
let activeEventsItemContainer;
// initalize variables to figure out if user is actually tapping or swiping on mobile
let startY;
let yDistance;
// touch event handler to store touches
let touchHandler = event => {
touch = event.changedTouches[0];
};
mobileEventsButtons.forEach(button => {
// user first touches the mobile events button on screen
button.addEventListener('touchstart', touchHandler);
// user is currently touching button is also swiping
button.addEventListener('touchmove', touchHandler);
// store the current y position when user starts the touch of button
button.addEventListener('touchstart', () => {
startY = touch.clientY;
});
/* compare y distance from the point when user first touched the screen to when user lifts finger
off screen */
button.addEventListener('touchend', event => {
yDistance = startY - touch.clientY;
// if the distance is less than 30 pixels, it is a tap, not a swipe
if (Math.abs(yDistance) < 30) {
mobileEventsBackground.classList.remove('events-mobile-background-inactive');
// figure out which color and event description to display on click depending on id of button
switch (button.id) {
case 'first-mobile-event':
mobileEventsBackground.style.backgroundColor = csspiColor;
mobileEventsBackground.classList.add('events-mobile-background-active');
mobileCSSPI.classList.add('mobile-events-desc-container-active');
break;
case 'second-mobile-event':
mobileEventsBackground.style.backgroundColor = speakerColor;
mobileEventsBackground.classList.add('events-mobile-background-active');
mobileSpeaker.classList.add('mobile-events-desc-container-active');
break;
case 'third-mobile-event':
mobileEventsBackground.style.backgroundColor = workshopsColor;
mobileEventsBackground.classList.add('events-mobile-background-active');
mobileWorkshops.classList.add('mobile-events-desc-container-active');
break;
case 'fourth-mobile-event':
mobileEventsBackground.style.backgroundColor = recruiterColor;
mobileEventsBackground.classList.add('events-mobile-background-active');
mobileRecruiter.classList.add('mobile-events-desc-container-active');
break;
case 'fifth-mobile-event':
mobileEventsBackground.style.backgroundColor = webDesignColor;
mobileEventsBackground.classList.add('events-mobile-background-active');
mobileWebDesign.classList.add('mobile-events-desc-container-active');
break;
}
// set active item container
activeEventsItemContainer = document.querySelector('.mobile-events-desc-container-active');
}
});
});
// hide event description again after tapping on the transparent background or the event description itself
mobileEventsBackground.addEventListener('touchend', event => {
event.preventDefault();
// fade out background
mobileEventsBackground.classList.remove('events-mobile-background-active');
mobileEventsBackground.classList.add('events-mobile-background-inactive');
// fade out active event item container
activeEventsItemContainer.classList.remove('mobile-events-desc-container-active');
activeEventsItemContainer.classList.add('mobile-events-desc-container-inactive');
});
eventDescs.forEach(eventDesc => {
eventDesc.addEventListener('touchend', event => {
event.preventDefault();
// fade out background
mobileEventsBackground.classList.remove('events-mobile-background-active');
mobileEventsBackground.classList.add('events-mobile-background-inactive');
// fade out active event item container
activeEventsItemContainer.classList.remove('mobile-events-desc-container-active');
activeEventsItemContainer.classList.add('mobile-events-desc-container-inactive');
});
});
/*
==================================
Desktop Design
==================================
*/
/*
------------------------------------
6. Navigation bar color transition
------------------------------------
*/
const homepageOptions = {
// set the margin for when exactly the navigation bar changes color
rootMargin: '-10px'
};
const navbarOnScroll = new IntersectionObserver((entries, navbarOnScroll) => {
entries.forEach(entry => {
// if the homepage is not on the viewport and the user is on desktop window size
if (!entry.isIntersecting && desktop.matches) {
navbar.classList.add('navbar-scrolled');
}
else {
navbar.classList.remove('navbar-scrolled');
}
});
}, homepageOptions);
// desktop media query event listener so navigation bar animation only occurs on desktop window sizes
desktop.addEventListener('resize', navbarOnScroll.observe(homepage));
/*
--------------------------------------
7. Mission card description on hover
--------------------------------------
*/
const missionCard = document.querySelectorAll('.mission-card');
missionCard.forEach(card => {
// select all elements to be animated inside specific mission index card
const cardTitle = card.querySelector('.mission-card-title');
const cardDesc = card.querySelector('.mission-card-description');
const cardImg = card.querySelector('.mission-card-image');
// when the card item is hovered over
card.addEventListener('mouseover', function() {
cardTitle.classList.add('mission-card-title-hover');
cardDesc.classList.add('mission-card-description-hover');
/* check if the first card is selected because it requires different alignment to
match other cards */
if (cardImg.classList.contains('first-mission-card-image')) {
cardImg.classList.add('first-mission-card-image-hover');
}
else {
cardImg.classList.add('mission-card-image-hover');
}
});
// when the cursor leaves the card item
card.addEventListener('mouseout', function() {
cardTitle.classList.remove('mission-card-title-hover');
cardDesc.classList.remove('mission-card-description-hover');
cardImg.classList.remove('mission-card-image-hover');
/* check if the first card is selected because it requires different alignment to
match other cards */
if (cardImg.classList.contains('first-mission-card-image')) {
cardImg.classList.remove('first-mission-card-image-hover');
}
else {
cardImg.classList.remove('mission-card-image-hover');
}
});
});
/*
============================================
8. E-board picture and description carousel
============================================
*/
const eboardDescContainer = document.querySelector('.e-board-description-container');
const eboardDescriptions = document.querySelectorAll('.e-board-description');
const eboardCarousel = document.querySelector('.e-board-gallery');
const eboardPhotos = document.querySelectorAll('.e-board-picture');
const eboardCounter = document.querySelector('.e-board-gallery-counter');
const leftBttn = document.querySelector('#e-board-gallery-left-button');
const rightBttn = document.querySelector('#e-board-gallery-right-button');
// counter and size variables for array eboardPhotos
let counter = 0;
let photoSize = eboardPhotos[0].clientWidth;
let paragraphSize = eboardDescriptions[0].clientWidth;
// event listeners to buttons
leftBttn.addEventListener('click', ()=> {
// stop the translation when clicking left button when user has reached the beginning
if (counter >= 1) {
// remove active class and add inactive class to the current image and paragraph
eboardPhotos[counter].classList.add('e-board-picture-inactive');
eboardPhotos[counter].classList.remove('e-board-picture-active');
eboardDescriptions[counter].classList.add('e-board-description-inactive');
eboardDescriptions[counter].classList.remove('e-board-description-active');
// translate to the previous picture and paragraph
counter--;
// if the user is on desktop, translate the e-board photos, otherwise only change opacity
if (desktop.matches) {
eboardCarousel.style.transform = `translateX(${-photoSize * counter}px)`;
}
eboardDescContainer.style.transform = `translateX(${-paragraphSize * counter}px)`;
// update e-board gallery counter below the pictures
eboardCounter.innerHTML = `${counter + 1} / 8`;
/* increment counter and add the active photo class and remove the inactive class from the
element */
eboardPhotos[counter].classList.add('e-board-picture-active');
eboardPhotos[counter].classList.remove('e-board-picture-inactive');
eboardDescriptions[counter].classList.add('e-board-description-active');
eboardDescriptions[counter].classList.remove('e-board-description-inactive');
}
});
rightBttn.addEventListener('click', ()=> {
if (desktop.matches) {
// user is on desktop window size
}
else {
// user is on mobile
}
// stop the translation if clicking right button when user has reached the end
if (counter <= eboardDescriptions.length - 2) {
// remove active class and add inactive class to the previous image
eboardPhotos[counter].classList.add('e-board-picture-inactive');
eboardPhotos[counter].classList.remove('e-board-picture-active');
eboardDescriptions[counter].classList.add('e-board-description-inactive');
eboardDescriptions[counter].classList.remove('e-board-description-active');
// translate to the next picture
// if the user is on desktop, translate the e-board photos, otherwise only change opacity
if (desktop.matches) {
eboardCarousel.style.transform = `translateX(${-photoSize * (counter + 1)}px)`
}
eboardDescContainer.style.transform = `translateX(${-paragraphSize * (counter + 1)}px)`
/* increment counter and add the active photo class and remove the inactive class from the
element */
counter++;
eboardPhotos[counter].classList.add('e-board-picture-active');
eboardPhotos[counter].classList.remove('e-board-picture-inactive');
eboardDescriptions[counter].classList.add('e-board-description-active');
eboardDescriptions[counter].classList.remove('e-board-description-inactive');
// update e-board gallery counter below pictures
eboardCounter.innerHTML = `${counter + 1} / 8`;
}
});
/*
================================
9. Events tooltip show on click
================================
*/
const eventsItems = document.querySelectorAll('.events-item');
const eventsClickIndicator = document.querySelector('.events-click-indicator');
const eventsClickIndicatorLine = document.querySelector('.events-click-indicator-line');
const eventsReadMore = document.querySelector('.events-read-more');
eventsItems.forEach(eventsItem => {
// the tooltip is the next sibling after events item title
let tooltip = eventsItem.nextElementSibling;
eventsItem.addEventListener('click', () => {
if (tooltip.classList.contains('above-tooltip')) {
// the event tooltip is supposed to show above the event item
if (tooltip.classList.contains('above-tooltip-click')) {
// the event item has already been clicked on and tooltip is already visible on screen
eventsItem.style.color = 'var(--blue)';
tooltip.classList.remove('above-tooltip-click');
}
else {
// the event item has not been clicked on and tooltip is not on screen
eventsItem.style.color = 'white';
tooltip.classList.add('above-tooltip-click');
}
}
else {
// the tooltip is supposed to translate below the event item
if (tooltip.classList.contains('below-tooltip-click')) {
// the event item has already been clicked on and tooltip is already visible on screen
eventsItem.style.color = 'var(--blue)';
tooltip.classList.remove('below-tooltip-click');
}
else {
// the event item has not been clicked on and tooltip is not on screen
eventsItem.style.color = 'white';
tooltip.classList.add('below-tooltip-click');
// these only appear the first time user is on website and disappear after first click
// behavior can be changed here if needed later
eventsClickIndicator.style.opacity = 0;
eventsClickIndicatorLine.style.opacity = 0;
eventsReadMore.style.opacity = 0;
}
}
});
});
$(document).scroll(function() {
// get current scrollbar location
let scrollbarLocation = window.pageYOffset;
/*
===============================
10. Parallax scrolling effects
===============================
*/
/*
========================
About Section Parallax
========================
*/
const aboutOffset = about.getBoundingClientRect();
const aboutHeight = about.offsetHeight;
const blueLine = document.querySelector('.about-blue-line');
const parallaxOptions = {
};
const aboutObserver = new IntersectionObserver((entries, aboutObserver) => {
entries.forEach(entry => {
// make sure parallax effects only occur when the scroll position is near the page
if (entry.isIntersecting) {
/* - the math below basically simplifies to making sure the parallax is most obvious only when
the elements are on viewport
- the sign of the number being multiplied is important:
- negative for translating up while scrolling
- positive for translating down while scrolling
*/
aboutTitle.style.transform =
`translateY(${scrollbarLocation / (aboutOffset.top + aboutHeight) * -150 + 150}px)`;
aboutDesc.style.transform =
`translateY(${scrollbarLocation / (aboutOffset.top + aboutHeight) * -100 + 100}px)`;
if (desktop.matches) {
// do these animations only for desktop
// translate blue line in desktop
blueLine.style.transform =
`translateY(${scrollbarLocation / (aboutOffset.top + aboutHeight) * -150 + 150}px)`;
blueLine.style.height = `${viewportHeight + scrollbarLocation * 0.1}vh`;
// scale the computer gif up if scroll position above section
if (aboutOffset.top >= 0) {
typingComputer.style.transform =
`translateX(${scrollbarLocation / (aboutOffset.top + aboutHeight) * 150 - 120}px)
scale(${scrollbarLocation / (aboutOffset.top + aboutHeight) * 0.5 + 0.5})`
}
/* make the computer gif smaller up until the user has scrolled past the section by 25% of their viewport
height */
else if (aboutOffset.top >= -0.75 * viewportHeight) {
typingComputer.style.transform =
`translateX(${scrollbarLocation / (aboutOffset.top + aboutHeight) * -150 + 180}px)
scale(${scrollbarLocation / (aboutOffset.top + aboutHeight) * -0.5 + 1.5})`;
}
else {
/*reset element styles so flow of the page isn't interrupted by elements getting translated to extreme
values */
typingComputer.style.transform =
`translateX(${-250}px)
scale(${0.5})`
aboutTitle.style.transform = 'translateY(-150px)';
blueLine.style.transform = 'translateY(-150px)';
blueLine.style.height = '100vh';
aboutDesc.style.transform = 'translateY(-100px)';
}
}
else {
// do these separate parallax effects only for mobile
typingComputer.style.transform =
`translateY(${scrollbarLocation / (aboutOffset.top + aboutHeight) * -150 + 120}px)`;
}
}
});
}, parallaxOptions);
aboutObserver.observe(about);
/*
==========================
Mission Section Parallax
==========================
*/
const missionHeight = mission.offsetHeight;
const missionOffset = mission.getBoundingClientRect();
const missionTitle = document.querySelector('.mission-title');
const cardColumn1 = document.querySelector('#mission-card-column-1');
const cardColumn2 = document.querySelector('#mission-card-column-2');
const cardColumn3 = document.querySelector('#mission-card-column-3');
const missionObserver = new IntersectionObserver((entries, missionObserver) => {
entries.forEach(entry => {
if (entry.isIntersecting && desktop.matches) {
// these animations only run when user is on a desktop window size and mission section is on screen
// effects when scroll position is above the section
missionTitle.style.transform =
`translateY(${scrollbarLocation / (missionOffset.top + missionHeight) * -175 + 350}px)`;
cardColumn1.style.transform =
`translateY(${scrollbarLocation / (missionOffset.top + missionHeight) * -200 + 400}px)`;
cardColumn2.style.transform =
`translateY(${scrollbarLocation / (missionOffset.top + missionHeight) * -150 + 300}px)`;
cardColumn3.style.transform =
`translateY(${scrollbarLocation / (missionOffset.top + missionHeight) * -100 + 200}px)`;
}
else {
missionTitle.style.transform = 'translateY(0px)';
cardColumn1.style.transform = 'translateY(0px)';
cardColumn2.style.transform = 'translateY(0px)';
cardColumn3.style.transform = 'translateY(0px)';
}
});
}, parallaxOptions);
missionObserver.observe(mission);
/*
==========================
E-board Section Parallax
==========================
*/
const eboardHeight = eboard.offsetHeight;
const eboardOffset = eboard.getBoundingClientRect();
const eboardTitle = document.querySelector('.e-board-title');
const eboardDesc = document.querySelector('.e-board-description');
const eboardGallery = document.querySelector('.e-board-gallery-container');
const eboardObserver = new IntersectionObserver((entries, eboardObserver) => {
entries.forEach(entry => {
});
}, parallaxOptions);
});
});