121 lines
3.8 KiB
JavaScript
121 lines
3.8 KiB
JavaScript
/**
|
|
* Lumerel — 3D Homepage
|
|
* main.js
|
|
*
|
|
* Handles:
|
|
* - Spline 3D scene loading & pointer-events toggle
|
|
* - Navbar scroll behaviour
|
|
* - Video fallback
|
|
* - Utility helpers for future Spline integration
|
|
*/
|
|
|
|
/* ── Spline Integration Helper ───────────────────────────────
|
|
*
|
|
* When you're ready to add a Spline scene:
|
|
*
|
|
* 1. Import the runtime:
|
|
* import { Application } from '@splinetool/runtime';
|
|
*
|
|
* 2. Or use the <spline-viewer> web component already loaded
|
|
* via the CDN script in index.html.
|
|
*
|
|
* 3. Replace the .hero__3d-placeholder div in index.html with:
|
|
* <spline-viewer
|
|
* url="https://prod.spline.design/YOUR_SCENE_ID/scene.splinecode"
|
|
* events-target="global"
|
|
* ></spline-viewer>
|
|
*
|
|
* 4. Call enableSplinePointerEvents() below to allow mouse
|
|
* interaction with the 3D scene.
|
|
*/
|
|
|
|
const splineLayer = document.getElementById('spline-layer');
|
|
|
|
/**
|
|
* Enable pointer events on the 3D layer so Spline scenes
|
|
* can receive mouse/touch input.
|
|
* Call this once your Spline scene is loaded.
|
|
*/
|
|
function enableSplinePointerEvents() {
|
|
if (splineLayer) {
|
|
splineLayer.style.pointerEvents = 'auto';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable pointer events on the 3D layer (default state).
|
|
* Keeps UI elements fully clickable.
|
|
*/
|
|
function disableSplinePointerEvents() {
|
|
if (splineLayer) {
|
|
splineLayer.style.pointerEvents = 'none';
|
|
}
|
|
}
|
|
|
|
// Listen for the spline-viewer ready event (web component)
|
|
if (splineLayer) {
|
|
const viewer = splineLayer.querySelector('spline-viewer');
|
|
if (viewer) {
|
|
viewer.addEventListener('load', () => {
|
|
console.log('[Lumerel] Spline scene loaded.');
|
|
// Uncomment to enable 3D interactivity:
|
|
// enableSplinePointerEvents();
|
|
});
|
|
}
|
|
}
|
|
|
|
/* ── Navbar Scroll Effect ─────────────────────────────────── */
|
|
const navbar = document.querySelector('.navbar');
|
|
|
|
function handleNavbarScroll() {
|
|
if (!navbar) return;
|
|
if (window.scrollY > 20) {
|
|
navbar.style.backdropFilter = 'blur(12px)';
|
|
navbar.style.background = 'rgba(0,0,0,0.35)';
|
|
navbar.style.transition = 'background 0.3s ease, backdrop-filter 0.3s ease';
|
|
} else {
|
|
navbar.style.backdropFilter = 'none';
|
|
navbar.style.background = 'transparent';
|
|
}
|
|
}
|
|
|
|
window.addEventListener('scroll', handleNavbarScroll, { passive: true });
|
|
handleNavbarScroll(); // run on load
|
|
|
|
/* ── Video Fallback ───────────────────────────────────────── */
|
|
const heroVideo = document.querySelector('.hero__video');
|
|
|
|
if (heroVideo) {
|
|
heroVideo.addEventListener('error', () => {
|
|
console.warn('[Lumerel] Background video failed to load. Falling back to solid background.');
|
|
const videoWrap = document.querySelector('.hero__video-wrap');
|
|
if (videoWrap) {
|
|
videoWrap.style.background = 'linear-gradient(135deg, #0a0a0a 0%, #111 100%)';
|
|
}
|
|
});
|
|
|
|
// Ensure autoplay works after user interaction on iOS
|
|
document.addEventListener('touchstart', () => {
|
|
if (heroVideo.paused) {
|
|
heroVideo.play().catch(() => {});
|
|
}
|
|
}, { once: true });
|
|
}
|
|
|
|
/* ── Waitlist Button Handlers ─────────────────────────────── */
|
|
const waitlistBtns = document.querySelectorAll('.btn-pill');
|
|
|
|
waitlistBtns.forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
// Replace with your actual waitlist modal / form logic
|
|
console.log('[Lumerel] Join Waitlist clicked.');
|
|
// Example: openWaitlistModal();
|
|
});
|
|
});
|
|
|
|
/* ── Expose helpers globally for console/debugging ─────────── */
|
|
window.Lumerel = {
|
|
enableSplinePointerEvents,
|
|
disableSplinePointerEvents,
|
|
};
|