81 lines
2.3 KiB
JavaScript
81 lines
2.3 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
|
const navLinks = document.querySelectorAll('nav a');
|
|
const sections = document.querySelectorAll('section');
|
|
|
|
// Smooth scroll with offset for sticky header/sidebar
|
|
navLinks.forEach(link => {
|
|
link.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
const targetId = link.getAttribute('href').substring(1);
|
|
const targetElement = document.getElementById(targetId);
|
|
|
|
if (targetElement) {
|
|
window.scrollTo({
|
|
top: targetElement.offsetTop - 50,
|
|
behavior: 'smooth'
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
// Intersection Observer for Sidebar Active State
|
|
const observerOptions = {
|
|
root: null,
|
|
rootMargin: '-20% 0px -70% 0px',
|
|
threshold: 0
|
|
};
|
|
|
|
const observer = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
const id = entry.target.getAttribute('id');
|
|
navLinks.forEach(link => {
|
|
link.classList.remove('active');
|
|
if (link.getAttribute('href') === `#${id}`) {
|
|
link.classList.add('active');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}, observerOptions);
|
|
|
|
sections.forEach(section => observer.observe(section));
|
|
|
|
// Advanced Reveal Animations on Scroll
|
|
const revealElements = document.querySelectorAll('.deep-dive, .tech-card, .highlight-box, pre');
|
|
|
|
const revealObserver = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('revealed');
|
|
}
|
|
});
|
|
}, { threshold: 0.1 });
|
|
|
|
revealElements.forEach(el => {
|
|
el.style.opacity = '0';
|
|
el.style.transform = 'translateY(40px)';
|
|
el.style.transition = 'all 1s cubic-bezier(0.2, 0.8, 0.2, 1)';
|
|
revealObserver.observe(el);
|
|
});
|
|
|
|
// CSS injection for reveal animation class
|
|
const style = document.createElement('style');
|
|
style.textContent = `
|
|
.revealed {
|
|
opacity: 1 !important;
|
|
transform: translateY(0) !important;
|
|
}
|
|
`;
|
|
document.head.appendChild(style);
|
|
|
|
// Parallax Hero Effect
|
|
window.addEventListener('scroll', () => {
|
|
const hero = document.querySelector('.hero-img');
|
|
const scroll = window.pageYOffset;
|
|
if (hero) {
|
|
hero.style.transform = `scale(1.1) translateY(${scroll * 0.4}px)`;
|
|
}
|
|
});
|
|
});
|