Spaces:
Running
Running
File size: 4,859 Bytes
9b00824 |
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 |
// Main JavaScript for CodeCanvas Noir Portfolio
class PortfolioApp {
constructor() {
this.init();
}
init() {
this.setupScrollAnimations();
this.setupIntersectionObserver();
this.setupSmoothScrolling();
this.setupProjectCards();
}
setupScrollAnimations() {
// Add scroll-triggered animations
window.addEventListener('scroll', this.handleScroll.bind(this));
}
setupIntersectionObserver() {
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-fade-in');
}
});
}, observerOptions);
// Observe all sections for animation
document.querySelectorAll('section').forEach(section => {
observer.observe(section);
});
}
setupSmoothScrolling() {
// 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) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
}
setupProjectCards() {
// Add tilt effect to project cards
const projectCards = document.querySelectorAll('.project-card');
projectCards.forEach(card => {
card.addEventListener('mousemove', this.handleTilt.bind(this));
card.addEventListener('mouseleave', this.resetTilt.bind(this));
});
}
handleTilt(e) {
const card = e.currentTarget;
const cardRect = card.getBoundingClientRect();
const cardCenterX = cardRect.left + cardRect.width / 2;
const cardCenterY = cardRect.top + cardRect.height / 2;
const mouseX = e.clientX - cardCenterX;
const mouseY = e.clientY - cardCenterY;
const rotateX = (mouseY / cardRect.height) * 10;
const rotateY = -(mouseX / cardRect.width) * 10;
card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.02, 1.02, 1.02);
}
resetTilt(e) {
const card = e.currentTarget;
card.style.transform = 'perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)';
}
handleScroll() {
// Update navigation active state based on scroll position
this.updateNavigation();
}
updateNavigation() {
const sections = document.querySelectorAll('section');
const navLinks = document.querySelectorAll('nav a');
let currentSection = '';
sections.forEach(section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.clientHeight;
if (window.scrollY >= sectionTop - 100 && window.scrollY < sectionTop + sectionHeight - 100) {
currentSection = section.getAttribute('id');
}
});
navLinks.forEach(link => {
link.classList.remove('nav-active');
if (link.getAttribute('href') === `#${currentSection}`) {
link.classList.add('nav-active');
}
});
}
// Utility method for debouncing
debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
}
// Initialize the portfolio app when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
new PortfolioApp();
});
// Handle page visibility changes for performance
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
// Page is hidden, pause heavy animations if any
} else {
// Page is visible, resume animations
}
});
// Handle resize events with debouncing
window.addEventListener('resize', debounce(() => {
// Handle responsive adjustments
}, 250));
// Helper function for debouncing
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
} |