Spaces:
Running
Running
File size: 5,902 Bytes
e952035 | 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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | // ── LOADER
window.addEventListener('load', () => {
setTimeout(() => {
document.getElementById('loader').classList.add('hidden');
}, 2000);
});
// ── CUSTOM CURSOR
const cursor = document.getElementById('cursor');
const follower = document.getElementById('cursor-follower');
let mouseX = 0, mouseY = 0;
let followerX = 0, followerY = 0;
document.addEventListener('mousemove', (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
cursor.style.transform = `translate(${mouseX - 4}px, ${mouseY - 4}px)`;
});
function animateFollower() {
followerX += (mouseX - followerX) * 0.12;
followerY += (mouseY - followerY) * 0.12;
follower.style.transform = `translate(${followerX - 18}px, ${followerY - 18}px)`;
requestAnimationFrame(animateFollower);
}
animateFollower();
document.querySelectorAll('a, button, .portfolio-item, .filter-btn').forEach(el => {
el.addEventListener('mouseenter', () => {
cursor.style.transform += ' scale(2)';
follower.style.width = '60px';
follower.style.height = '60px';
follower.style.opacity = '0.5';
});
el.addEventListener('mouseleave', () => {
follower.style.width = '36px';
follower.style.height = '36px';
follower.style.opacity = '1';
});
});
// ── NAV SCROLL
const nav = document.getElementById('nav');
window.addEventListener('scroll', () => {
nav.classList.toggle('scrolled', window.scrollY > 60);
});
// ── MOBILE MENU
const hamburger = document.getElementById('hamburger');
let mobileMenu = document.createElement('div');
mobileMenu.className = 'mobile-menu';
const menuLinks = ['#about|O Nas', '#portfolio|Portfolio', '#process|Proces', '#testimonials|Opinie', '#contact|Kontakt'];
menuLinks.forEach(item => {
const [href, label] = item.split('|');
const a = document.createElement('a');
a.href = href;
a.textContent = label;
a.addEventListener('click', () => mobileMenu.classList.remove('open'));
mobileMenu.appendChild(a);
});
document.body.appendChild(mobileMenu);
hamburger.addEventListener('click', () => {
mobileMenu.classList.toggle('open');
});
// ── COUNTER ANIMATION
function animateCounter(el) {
const target = parseInt(el.getAttribute('data-count'));
const duration = 2000;
const start = performance.now();
function update(time) {
const elapsed = time - start;
const progress = Math.min(elapsed / duration, 1);
const eased = 1 - Math.pow(1 - progress, 3);
el.textContent = Math.round(eased * target);
if (progress < 1) requestAnimationFrame(update);
}
requestAnimationFrame(update);
}
// ── INTERSECTION OBSERVER
const observerOptions = { threshold: 0.15, rootMargin: '0px 0px -60px 0px' };
const revealObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
revealObserver.unobserve(entry.target);
}
});
}, observerOptions);
document.querySelectorAll('.about-grid, .portfolio-item, .process-step, .testimonial-card, .award-item, .contact-grid, .fp-content, .section-header').forEach((el, i) => {
el.classList.add('reveal');
revealObserver.observe(el);
});
const counterObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
animateCounter(entry.target);
counterObserver.unobserve(entry.target);
}
});
}, { threshold: 0.5 });
document.querySelectorAll('.stat-num').forEach(el => counterObserver.observe(el));
// ── PORTFOLIO FILTER
const filterBtns = document.querySelectorAll('.filter-btn');
const portfolioItems = document.querySelectorAll('.portfolio-item');
filterBtns.forEach(btn => {
btn.addEventListener('click', () => {
filterBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
const filter = btn.getAttribute('data-filter');
portfolioItems.forEach(item => {
const cat = item.getAttribute('data-category');
if (filter === 'all' || cat === filter) {
item.style.opacity = '1';
item.style.transform = 'scale(1)';
item.style.display = '';
} else {
item.style.opacity = '0';
item.style.transform = 'scale(0.95)';
setTimeout(() => { if (filter !== 'all' && cat !== filter) item.style.display = 'none'; }, 300);
}
});
});
});
// ── SMOOTH SCROLL
document.querySelectorAll('a[href^="#"]').forEach(a => {
a.addEventListener('click', (e) => {
const target = document.querySelector(a.getAttribute('href'));
if (target) {
e.preventDefault();
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
});
// ── PARALLAX HERO
window.addEventListener('scroll', () => {
const scrollY = window.scrollY;
const heroImg = document.querySelector('.hero-img');
const orbs = document.querySelectorAll('.hero-orb');
if (heroImg) heroImg.style.transform = `scale(1.05) translateY(${scrollY * 0.12}px)`;
orbs.forEach((orb, i) => {
orb.style.transform = `translateY(${scrollY * (0.05 + i * 0.03)}px)`;
});
});
// ── FORM SUBMIT
document.getElementById('contactForm')?.addEventListener('submit', (e) => {
e.preventDefault();
const btn = e.target.querySelector('.btn-primary');
const original = btn.innerHTML;
btn.innerHTML = '<span>Wysłano! Odezwiemy się wkrótce ✓</span>';
btn.style.background = '#2D7A3A';
setTimeout(() => {
btn.innerHTML = original;
btn.style.background = '';
e.target.reset();
}, 4000);
});
// ── STAGGER CHILDREN
document.querySelectorAll('.process-steps .process-step').forEach((el, i) => {
el.style.transitionDelay = `${i * 0.12}s`;
});
document.querySelectorAll('.testimonials-grid .testimonial-card').forEach((el, i) => {
el.style.transitionDelay = `${i * 0.1}s`;
});
document.querySelectorAll('.portfolio-item').forEach((el, i) => {
el.style.transitionDelay = `${i * 0.08}s`;
}); |