You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
6.4 KiB

class PortfolioAnimations {
constructor() {
this.init();
}
init() {
this.setupIntersectionObserver();
this.setupMagneticEffects();
this.setupParallaxEffects();
this.addFloatingShapes();
}
setupIntersectionObserver() {
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const element = entry.target;
const animation = element.dataset.animation;
const delay = element.dataset.delay || 0;
setTimeout(() => {
element.classList.add(`animate-${animation}`);
if (element.dataset.counter) {
this.animateCounter(element);
}
}, delay);
observer.unobserve(element);
}
});
}, observerOptions);
document.querySelectorAll('.animate-on-scroll').forEach(el => {
observer.observe(el);
});
}
setupMagneticEffects() {
document.querySelectorAll('.magnetic').forEach(button => {
button.addEventListener('mousemove', (e) => {
const rect = button.getBoundingClientRect();
const x = e.clientX - rect.left - rect.width / 2;
const y = e.clientY - rect.top - rect.height / 2;
button.style.transform = `translate(${x * 0.1}px, ${y * 0.1}px) scale(1.02)`;
});
button.addEventListener('mouseleave', () => {
button.style.transform = 'translate(0px, 0px) scale(1)';
});
});
}
setupParallaxEffects() {
window.addEventListener('scroll', () => {
const scrolled = window.pageYOffset;
const parallaxElements = document.querySelectorAll('.parallax');
parallaxElements.forEach(element => {
const speed = element.dataset.speed || 0.5;
const yPos = -(scrolled * speed);
element.style.transform = `translateY(${yPos}px)`;
});
});
}
animateCounter(element) {
const target = parseInt(element.dataset.counter);
const duration = 2000;
const start = 0;
const increment = target / (duration / 16);
let current = start;
const timer = setInterval(() => {
current += increment;
if (current >= target) {
current = target;
clearInterval(timer);
}
element.textContent = Math.floor(current);
}, 16);
}
addFloatingShapes() {
const hero = document.querySelector('.hero-gradient');
if (!hero) return;
const shapesContainer = document.createElement('div');
shapesContainer.className = 'floating-shapes';
for (let i = 0; i < 3; i++) {
const shape = document.createElement('div');
shape.className = 'floating-shape';
shapesContainer.appendChild(shape);
}
hero.appendChild(shapesContainer);
}
static typeWriter(element, text, speed = 100) {
let i = 0;
element.textContent = '';
function type() {
if (i < text.length) {
element.textContent += text.charAt(i);
i++;
setTimeout(type, speed);
}
}
type();
}
static revealText(element) {
const text = element.textContent;
const words = text.split(' ');
element.innerHTML = '';
words.forEach((word, index) => {
const span = document.createElement('span');
span.textContent = word + ' ';
span.style.opacity = '0';
span.style.transform = 'translateY(20px)';
span.style.transition = `all 0.6s ease ${index * 0.1}s`;
element.appendChild(span);
setTimeout(() => {
span.style.opacity = '1';
span.style.transform = 'translateY(0)';
}, 100);
});
}
static setupSmoothScroll() {
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'
});
}
});
});
}
}
document.addEventListener('DOMContentLoaded', () => {
new PortfolioAnimations();
PortfolioAnimations.setupSmoothScroll();
});
window.PortfolioAnimations = PortfolioAnimations;
function initScrollAnimations() {
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const delay = entry.target.dataset.delay || 0;
setTimeout(() => {
entry.target.classList.add('visible');
}, delay);
}
});
}, observerOptions);
document.querySelectorAll('.animate-on-scroll').forEach(el => {
observer.observe(el);
});
}
function initMagneticEffect() {
const magneticElements = document.querySelectorAll('.magnetic');
magneticElements.forEach(el => {
el.addEventListener('mousemove', (e) => {
const rect = el.getBoundingClientRect();
const x = e.clientX - rect.left - rect.width / 2;
const y = e.clientY - rect.top - rect.height / 2;
el.style.transform = `translate(${x * 0.1}px, ${y * 0.1}px) scale(1.02)`;
});
el.addEventListener('mouseleave', () => {
el.style.transform = 'translate(0px, 0px) scale(1)';
});
});
}
document.addEventListener('DOMContentLoaded', () => {
initScrollAnimations();
initMagneticEffect();
});