-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
149 lines (123 loc) · 4.65 KB
/
script.js
File metadata and controls
149 lines (123 loc) · 4.65 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
// Smooth scrolling for navigation links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
// Remove active class from all links
document.querySelectorAll('.nav-link').forEach(link => {
link.classList.remove('active');
});
// Add active class to clicked link
this.classList.add('active');
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
// Refresh AOS after smooth scroll to trigger animations
setTimeout(() => {
if (typeof AOS !== 'undefined') {
AOS.refresh();
}
}, 800);
}
});
});
// Add active class to navigation links based on scroll position
window.addEventListener('scroll', () => {
const sections = document.querySelectorAll('.section');
const navLinks = document.querySelectorAll('.nav-link');
let current = '';
sections.forEach(section => {
const sectionTop = section.offsetTop;
if (scrollY >= (sectionTop - 200)) {
current = section.getAttribute('id');
}
});
navLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === `#${current}`) {
link.classList.add('active');
}
});
// Refresh AOS on scroll to ensure animations trigger properly
if (typeof AOS !== 'undefined') {
AOS.refresh();
}
// Enhanced AOS refresh when scrolling up
let currentScrollTop = window.pageYOffset || document.documentElement.scrollTop;
if (currentScrollTop < lastScrollTop) {
// Scrolling up - refresh AOS more aggressively
if (typeof AOS !== 'undefined') {
AOS.refresh();
// Force refresh after a short delay to ensure animations trigger
setTimeout(() => {
AOS.refresh();
}, 100);
}
}
lastScrollTop = currentScrollTop;
});
// Add loading animation for Spline iframe
window.addEventListener('load', () => {
const iframe = document.querySelector('#home iframe');
if (iframe) {
iframe.style.opacity = '0';
iframe.style.transition = 'opacity 0.8s ease';
setTimeout(() => {
iframe.style.opacity = '1';
}, 500);
}
});
// Show back-to-top button after hero and hide/show header on scroll
(() => {
let lastScrollTop = 0;
const header = document.querySelector('.navbar');
const toTop = document.querySelector('.to-top');
const heroSection = document.querySelector('#home');
if (!header || !toTop || !heroSection) return;
window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const heroSectionOffsetTop = heroSection.offsetTop + heroSection.offsetHeight;
if (scrollTop > heroSectionOffsetTop) {
toTop.classList.add('active');
} else {
toTop.classList.remove('active');
}
if (scrollTop > lastScrollTop) {
header.classList.add('hidden');
} else {
header.classList.remove('hidden');
}
lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; // avoid negative on iOS
}, { passive: true });
})();
// Theme toggle: persist to localStorage and apply body[data-theme]
(() => {
const STORAGE_KEY = 'theme';
function setTheme(theme) {
document.body.setAttribute('data-theme', theme);
try { localStorage.setItem(STORAGE_KEY, theme); } catch (e) { /* ignore */ }
const toggle = document.getElementById('theme-toggle');
if (toggle) toggle.checked = theme === 'dark';
}
function initTheme() {
let saved = null;
try { saved = localStorage.getItem(STORAGE_KEY); } catch (e) { /* ignore */ }
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
const initial = saved || (prefersDark ? 'dark' : 'light');
setTheme(initial);
const toggle = document.getElementById('theme-toggle');
if (toggle) {
toggle.addEventListener('change', (e) => {
const isDark = e.target.checked;
setTheme(isDark ? 'dark' : 'light');
});
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initTheme);
} else {
initTheme();
}
})();