interior-home2 / script.js
adowu's picture
Launch: Advanced interior architect portfolio landing page
e952035 verified
// ── 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`;
});