chchchadzilla's picture
Initial DeepSite commit
968cef6 verified
Raw
History Blame Contribute Delete
10.1 kB
// Initialize Lucide Icons
lucide.createIcons();
// Register GSAP plugins
gsap.registerPlugin(ScrollTrigger);
// ==========================================
// CUSTOM CURSOR
// ==========================================
const cursorDot = document.querySelector('.cursor-dot');
const cursorOutline = document.querySelector('.cursor-outline');
if (window.matchMedia("(min-width: 768px)").matches) {
window.addEventListener('mousemove', (e) => {
const posX = e.clientX;
const posY = e.clientY;
// Dot follows immediately
cursorDot.style.left = `${posX}px`;
cursorDot.style.top = `${posY}px`;
// Outline follows with slight delay (using GSAP for smoothness)
gsap.to(cursorOutline, {
x: posX,
y: posY,
duration: 0.15,
ease: "power2.out"
});
});
// Hover effects for interactive elements
const interactiveElements = document.querySelectorAll('a, button, .tilt-card, input, textarea');
interactiveElements.forEach(el => {
el.addEventListener('mouseenter', () => {
document.body.classList.add('hovering');
gsap.to(cursorOutline, {
scale: 1.5,
duration: 0.3
});
});
el.addEventListener('mouseleave', () => {
document.body.classList.remove('hovering');
gsap.to(cursorOutline, {
scale: 1,
duration: 0.3
});
});
});
}
// ==========================================
// REVERSE COMPASS SCROLLBAR
// ==========================================
// The compass needle moves UP when scrolling DOWN (reverse behavior)
// and rotates based on scroll velocity
const compassNeedle = document.getElementById('compassNeedle');
let lastScrollY = window.scrollY;
let scrollVelocity = 0;
function updateCompassScroll() {
const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
const scrollTop = window.scrollY;
const scrollPercent = scrollTop / scrollHeight;
// Reverse behavior: needle moves up as page scrolls down
const containerHeight = 200; // height of scroll container
const needlePosition = containerHeight - (scrollPercent * containerHeight);
if (compassNeedle) {
compassNeedle.style.top = `${needlePosition}px`;
// Calculate velocity for rotation
scrollVelocity = scrollTop - lastScrollY;
const rotation = scrollVelocity * 2; // amplify rotation
gsap.to(compassNeedle, {
rotation: rotation,
duration: 0.1
});
}
lastScrollY = scrollTop;
}
// Throttled scroll listener
let ticking = false;
window.addEventListener('scroll', () => {
if (!ticking) {
window.requestAnimationFrame(() => {
updateCompassScroll();
ticking = false;
});
ticking = true;
}
});
// ==========================================
// D3 COMPASS VISUALIZATION (Hero Background)
// ==========================================
const initD3Compass = () => {
const width = window.innerWidth;
const height = window.innerHeight;
const svg = d3.select("#compass-viz")
.append("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", `0 0 ${width} ${height}`);
const centerX = width / 2;
const centerY = height / 2;
// Create concentric circles
const circles = [100, 200, 300, 400];
circles.forEach(radius => {
svg.append("circle")
.attr("cx", centerX)
.attr("cy", centerY)
.attr("r", radius)
.attr("class", "compass-circle");
});
// Create compass rose lines
for (let i = 0; i < 360; i += 30) {
const angle = (i * Math.PI) / 180;
const x2 = centerX + Math.cos(angle) * 400;
const y2 = centerY + Math.sin(angle) * 400;
svg.append("line")
.attr("x1", centerX)
.attr("y1", centerY)
.attr("x2", x2)
.attr("y2", y2)
.attr("class", "compass-rose-line");
}
// Animate on scroll
gsap.to(".compass-circle", {
scrollTrigger: {
trigger: "body",
start: "top top",
end: "bottom bottom",
scrub: 1
},
attr: { r: (i, target) => 100 + (i * 100) + 50 },
opacity: 0
});
gsap.to(".compass-rose-line", {
scrollTrigger: {
trigger: "body",
start: "top top",
end: "bottom bottom",
scrub: 1
},
rotation: 45,
transformOrigin: "center"
});
};
if (window.matchMedia("(min-width: 1024px)").matches) {
initD3Compass();
}
// ==========================================
// TEXT REVEAL ANIMATIONS
// ==========================================
const lineInners = document.querySelectorAll('.line-inner');
lineInners.forEach((line, index) => {
gsap.to(line, {
y: 0,
duration: 1,
ease: "power4.out",
delay: index * 0.1,
scrollTrigger: {
trigger: line,
start: "top 85%",
toggleActions: "play none none none"
}
});
});
// Hero subtext fade in
gsap.to("#heroSubtext", {
opacity: 1,
y: 0,
duration: 1,
delay: 0.5,
ease: "power2.out"
});
// ==========================================
// PARALLAX BACKGROUND GRID
// ==========================================
const gridBg = document.getElementById('gridBg');
if (gridBg) {
gsap.to(gridBg, {
scrollTrigger: {
trigger: "body",
start: "top top",
end: "bottom bottom",
scrub: 0.5
},
backgroundPosition: "50% 100%"
});
}
// ==========================================
// 3D TILT EFFECTS ON CARDS
// ==========================================
const tiltCards = document.querySelectorAll('.tilt-card');
tiltCards.forEach(card => {
card.addEventListener('mousemove', (e) => {
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) / centerY * -10; // Max 10deg rotation
const rotateY = (x - centerX) / centerX * 10;
gsap.to(card, {
rotationX: rotateX,
rotationY: rotateY,
transformPerspective: 1000,
duration: 0.3,
ease: "power2.out"
});
});
card.addEventListener('mouseleave', () => {
gsap.to(card, {
rotationX: 0,
rotationY: 0,
duration: 0.5,
ease: "power2.out"
});
});
});
// ==========================================
// NAVIGATION SHOW/HIDE ON SCROLL
// ==========================================
const nav = document.getElementById('mainNav');
let lastScroll = 0;
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
if (currentScroll > 100) {
if (currentScroll > lastScroll) {
// Scrolling down
nav.classList.remove('nav-visible');
nav.classList.add('nav-hidden');
} else {
// Scrolling up
nav.classList.remove('nav-hidden');
nav.classList.add('nav-visible');
}
} else {
nav.classList.add('nav-hidden');
nav.classList.remove('nav-visible');
}
lastScroll = currentScroll;
});
// ==========================================
// FAQ ACCORDION
// ==========================================
function toggleFaq(element) {
const content = element.querySelector('.faq-content');
const isActive = element.classList.contains('active');
// Close all others
document.querySelectorAll('.faq-item').forEach(item => {
item.classList.remove('active');
item.querySelector('.faq-content').classList.remove('active');
});
// Open clicked if it wasn't active
if (!isActive) {
element.classList.add('active');
content.classList.add('active');
}
}
// ==========================================
// SMOOTH SCROLL 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'
});
}
});
});
// ==========================================
// MAGNETIC BUTTON EFFECT
// ==========================================
const magneticBtns = document.querySelectorAll('.magnetic-btn');
magneticBtns.forEach(btn => {
btn.addEventListener('mousemove', (e) => {
const rect = btn.getBoundingClientRect();
const x = e.clientX - rect.left - rect.width / 2;
const y = e.clientY - rect.top - rect.height / 2;
gsap.to(btn, {
x: x * 0.3,
y: y * 0.3,
duration: 0.3,
ease: "power2.out"
});
});
btn.addEventListener('mouseleave', () => {
gsap.to(btn, {
x: 0,
y: 0,
duration: 0.5,
ease: "elastic.out(1, 0.3)"
});
});
});
// ==========================================
// IMAGE PARALLAX EFFECT
// ==========================================
const parallaxImages = document.querySelectorAll('.parallax-img');
parallaxImages.forEach(img => {
const speed = img.getAttribute('data-speed') || 0.5;
gsap.to(img, {
scrollTrigger: {
trigger: img.parentElement,
start: "top bottom",
end: "bottom top",
scrub: true
},
y: -50 * speed,
scale: 1.1
});
});