-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
144 lines (124 loc) · 4.72 KB
/
script.js
File metadata and controls
144 lines (124 loc) · 4.72 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
// Mobile Navigation Toggle
const navToggle = document.getElementById('navToggle');
const navMenu = document.getElementById('navMenu');
const navLinks = document.querySelectorAll('.nav-link');
navToggle.addEventListener('click', () => {
navToggle.classList.toggle('active');
navMenu.classList.toggle('active');
});
// Close mobile menu when clicking a link
navLinks.forEach(link => {
link.addEventListener('click', () => {
navToggle.classList.remove('active');
navMenu.classList.remove('active');
});
});
// Smooth scrolling for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
const offset = 80;
const targetPosition = target.offsetTop - offset;
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
}
});
});
// Active navigation link based on scroll position
const sections = document.querySelectorAll('section[id]');
function highlightNavigation() {
const scrollPosition = window.scrollY + 100;
sections.forEach(section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.offsetHeight;
const sectionId = section.getAttribute('id');
if (scrollPosition >= sectionTop && scrollPosition < sectionTop + sectionHeight) {
navLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === `#${sectionId}`) {
link.classList.add('active');
}
});
}
});
}
window.addEventListener('scroll', highlightNavigation);
window.addEventListener('load', highlightNavigation);
// Intersection Observer for fade in animations
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -100px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Observe elements for animations (grouped per section to keep stagger short)
document.querySelectorAll('.module-card, .flow-step, .problem-card, .publication-card, .code-card').forEach(element => {
element.style.opacity = '0';
element.style.transform = 'translateY(20px)';
element.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
observer.observe(element);
});
// Animated section titles — split into letters on load, reveal on scroll
document.querySelectorAll('.section-title').forEach(title => {
const text = title.textContent;
title.innerHTML = '';
let charIndex = 0;
text.split(' ').forEach((word, wordIndex, arr) => {
const wordSpan = document.createElement('span');
wordSpan.style.display = 'inline-block';
wordSpan.style.whiteSpace = 'nowrap';
[...word].forEach(char => {
const span = document.createElement('span');
span.textContent = char;
span.className = 'title-char';
span.style.setProperty('--ci', charIndex++);
wordSpan.appendChild(span);
});
title.appendChild(wordSpan);
if (wordIndex < arr.length - 1) title.appendChild(document.createTextNode(' '));
});
});
const titleObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('revealed');
titleObserver.unobserve(entry.target);
}
});
}, { threshold: 0.3 });
document.querySelectorAll('.section-title').forEach(title => titleObserver.observe(title));
// Add scroll effect to navbar
let lastScroll = 0;
const navbar = document.querySelector('.navbar');
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
if (currentScroll > 100) {
navbar.style.boxShadow = '0 2px 20px rgba(0, 0, 0, 0.1)';
} else {
navbar.style.boxShadow = 'none';
}
lastScroll = currentScroll;
});
// Toggle hamburger menu animation
navToggle.addEventListener('click', () => {
const spans = navToggle.querySelectorAll('span');
if (navToggle.classList.contains('active')) {
spans[0].style.transform = 'rotate(45deg) translate(5px, 5px)';
spans[1].style.opacity = '0';
spans[2].style.transform = 'rotate(-45deg) translate(7px, -6px)';
} else {
spans[0].style.transform = 'none';
spans[1].style.opacity = '1';
spans[2].style.transform = 'none';
}
});