209 lines
5.9 KiB
JavaScript
209 lines
5.9 KiB
JavaScript
// Custom Cursor
|
|
const cursor = document.querySelector('.cursor');
|
|
const cursorFollower = document.querySelector('.cursor-follower');
|
|
|
|
if (cursor && cursorFollower) {
|
|
let mouseX = 0;
|
|
let mouseY = 0;
|
|
let followerX = 0;
|
|
let followerY = 0;
|
|
|
|
document.addEventListener('mousemove', (e) => {
|
|
mouseX = e.clientX;
|
|
mouseY = e.clientY;
|
|
cursor.style.left = mouseX + 'px';
|
|
cursor.style.top = mouseY + 'px';
|
|
});
|
|
|
|
function animateFollower() {
|
|
followerX += (mouseX - followerX) * 0.15;
|
|
followerY += (mouseY - followerY) * 0.15;
|
|
cursorFollower.style.left = followerX + 'px';
|
|
cursorFollower.style.top = followerY + 'px';
|
|
requestAnimationFrame(animateFollower);
|
|
}
|
|
animateFollower();
|
|
|
|
const hoverElements = document.querySelectorAll('a, button, .work-card');
|
|
hoverElements.forEach(el => {
|
|
el.addEventListener('mouseenter', () => {
|
|
cursor.classList.add('hover');
|
|
cursorFollower.classList.add('hover');
|
|
});
|
|
el.addEventListener('mouseleave', () => {
|
|
cursor.classList.remove('hover');
|
|
cursorFollower.classList.remove('hover');
|
|
});
|
|
});
|
|
}
|
|
|
|
// Navigation
|
|
const nav = document.querySelector('.nav');
|
|
const menuToggle = document.querySelector('.menu-toggle');
|
|
const mobileMenu = document.querySelector('.mobile-menu');
|
|
const mobileLinks = document.querySelectorAll('.mobile-link');
|
|
|
|
window.addEventListener('scroll', () => {
|
|
if (window.scrollY > 50) {
|
|
nav.classList.add('scrolled');
|
|
} else {
|
|
nav.classList.remove('scrolled');
|
|
}
|
|
});
|
|
|
|
menuToggle.addEventListener('click', () => {
|
|
menuToggle.classList.toggle('active');
|
|
mobileMenu.classList.toggle('active');
|
|
document.body.style.overflow = mobileMenu.classList.contains('active') ? 'hidden' : '';
|
|
});
|
|
|
|
mobileLinks.forEach(link => {
|
|
link.addEventListener('click', () => {
|
|
menuToggle.classList.remove('active');
|
|
mobileMenu.classList.remove('active');
|
|
document.body.style.overflow = '';
|
|
});
|
|
});
|
|
|
|
// Reveal on Scroll
|
|
const reveals = document.querySelectorAll('.reveal');
|
|
|
|
const revealObserver = new IntersectionObserver((entries) => {
|
|
entries.forEach((entry, index) => {
|
|
if (entry.isIntersecting) {
|
|
setTimeout(() => {
|
|
entry.target.classList.add('visible');
|
|
}, index * 100);
|
|
}
|
|
});
|
|
}, {
|
|
threshold: 0.1,
|
|
rootMargin: '0px 0px -50px 0px'
|
|
});
|
|
|
|
reveals.forEach(reveal => {
|
|
revealObserver.observe(reveal);
|
|
});
|
|
|
|
// Stats Counter
|
|
const stats = document.querySelectorAll('.stat-number');
|
|
let statsAnimated = false;
|
|
|
|
const statsObserver = new IntersectionObserver((entries) => {
|
|
if (entries[0].isIntersecting && !statsAnimated) {
|
|
statsAnimated = true;
|
|
stats.forEach(stat => {
|
|
const target = parseInt(stat.dataset.count);
|
|
let current = 0;
|
|
const duration = 2000;
|
|
const increment = target / (duration / 16);
|
|
|
|
const counter = setInterval(() => {
|
|
current += increment;
|
|
if (current >= target) {
|
|
stat.textContent = target;
|
|
clearInterval(counter);
|
|
} else {
|
|
stat.textContent = Math.floor(current);
|
|
}
|
|
}, 16);
|
|
});
|
|
}
|
|
}, { threshold: 0.5 });
|
|
|
|
const statsSection = document.querySelector('.stats-section');
|
|
if (statsSection) {
|
|
statsObserver.observe(statsSection);
|
|
}
|
|
|
|
// Form Handling
|
|
const contactForm = document.getElementById('contactForm');
|
|
|
|
if (contactForm) {
|
|
contactForm.addEventListener('submit', (e) => {
|
|
e.preventDefault();
|
|
|
|
const btn = contactForm.querySelector('button[type="submit"]');
|
|
const originalText = btn.innerHTML;
|
|
|
|
btn.innerHTML = '<span>שולח...</span>';
|
|
btn.disabled = true;
|
|
|
|
setTimeout(() => {
|
|
btn.innerHTML = '<span>נשלח בהצלחה! ✓</span>';
|
|
btn.style.background = 'var(--color-success)';
|
|
|
|
setTimeout(() => {
|
|
btn.innerHTML = originalText;
|
|
btn.style.background = '';
|
|
btn.disabled = false;
|
|
contactForm.reset();
|
|
}, 3000);
|
|
}, 1500);
|
|
});
|
|
}
|
|
|
|
// Smooth Scroll for Navigation Links
|
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
anchor.addEventListener('click', function (e) {
|
|
e.preventDefault();
|
|
const target = document.querySelector(this.getAttribute('href'));
|
|
if (target) {
|
|
const navHeight = nav.offsetHeight;
|
|
const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - navHeight;
|
|
window.scrollTo({
|
|
top: targetPosition,
|
|
behavior: 'smooth'
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
// Parallax effect on hero orbs
|
|
const orbs = document.querySelectorAll('.gradient-orb');
|
|
|
|
if (window.matchMedia('(prefers-reduced-motion: no-preference)').matches) {
|
|
window.addEventListener('scroll', () => {
|
|
const scrollY = window.scrollY;
|
|
orbs.forEach((orb, index) => {
|
|
const speed = (index + 1) * 0.1;
|
|
orb.style.transform = `translateY(${scrollY * speed}px)`;
|
|
});
|
|
});
|
|
}
|
|
|
|
// Work card hover effect
|
|
const workCards = document.querySelectorAll('.work-card');
|
|
|
|
workCards.forEach(card => {
|
|
card.addEventListener('mousemove', (e) => {
|
|
if (window.matchMedia('(prefers-reduced-motion: no-preference)').matches) {
|
|
const rect = card.getBoundingClientRect();
|
|
const x = e.clientX - rect.left;
|
|
const y = e.clientY - rect.top;
|
|
const centerX = rect.width / 2;
|
|
const centerY = rect.height / 2;
|
|
const rotateX = (y - centerY) / 20;
|
|
const rotateY = (centerX - x) / 20;
|
|
|
|
card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) translateY(-5px)`;
|
|
}
|
|
});
|
|
|
|
card.addEventListener('mouseleave', () => {
|
|
card.style.transform = '';
|
|
});
|
|
});
|
|
|
|
// Marquee pause on hover
|
|
const marquee = document.querySelector('.marquee');
|
|
|
|
if (marquee) {
|
|
marquee.addEventListener('mouseenter', () => {
|
|
marquee.querySelector('.marquee-track').style.animationPlayState = 'paused';
|
|
});
|
|
|
|
marquee.addEventListener('mouseleave', () => {
|
|
marquee.querySelector('.marquee-track').style.animationPlayState = 'running';
|
|
});
|
|
} |