141 lines
5.7 KiB
JavaScript
141 lines
5.7 KiB
JavaScript
/**
|
|
* Lumerel — 3D Homepage
|
|
* main.js
|
|
*
|
|
* Handles:
|
|
* - Spline 3D scene loading & pointer-events toggle
|
|
* - Navbar scroll behaviour (frosted glass on scroll)
|
|
* - Video autoplay fallback (iOS / autoplay-blocked browsers)
|
|
* - Waitlist button click handlers
|
|
* - Global helpers exposed on window.Lumerel
|
|
*/
|
|
|
|
/* ── Spline Integration ───────────────────────────────────────────
|
|
*
|
|
* WHEN YOUR SPLINE SCENE IS READY:
|
|
*
|
|
* 1. Open index.html and replace the .hero__3d-placeholder div
|
|
* with a <spline-viewer> element:
|
|
*
|
|
* <spline-viewer
|
|
* url="https://prod.spline.design/YOUR_SCENE_ID/scene.splinecode"
|
|
* events-target="global"
|
|
* ></spline-viewer>
|
|
*
|
|
* 2. To allow mouse/touch interaction on the 3D scene, call:
|
|
* window.Lumerel.enableSpline()
|
|
*
|
|
* 3. Optionally use the @splinetool/runtime package directly:
|
|
*
|
|
* import { Application } from '@splinetool/runtime';
|
|
* const app = new Application(canvas);
|
|
* app.load('https://prod.spline.design/YOUR_SCENE_ID/scene.splinecode');
|
|
*
|
|
* ─────────────────────────────────────────────────────────────── */
|
|
|
|
const splineLayer = document.getElementById('spline-layer');
|
|
|
|
/**
|
|
* Enable pointer events on the 3D layer so Spline scenes
|
|
* can receive mouse/touch input.
|
|
* Call this AFTER your Spline scene has loaded.
|
|
*/
|
|
function enableSpline() {
|
|
if (splineLayer) {
|
|
splineLayer.style.pointerEvents = 'auto';
|
|
console.log('[Lumerel] Spline pointer events ENABLED.');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable pointer events on the 3D layer (default state).
|
|
* Ensures all UI elements (buttons, links) remain fully clickable.
|
|
*/
|
|
function disableSpline() {
|
|
if (splineLayer) {
|
|
splineLayer.style.pointerEvents = 'none';
|
|
console.log('[Lumerel] Spline pointer events DISABLED.');
|
|
}
|
|
}
|
|
|
|
// Listen for the spline-viewer web component ready event
|
|
if (splineLayer) {
|
|
const viewer = splineLayer.querySelector('spline-viewer');
|
|
if (viewer) {
|
|
viewer.addEventListener('load', () => {
|
|
console.log('[Lumerel] Spline scene loaded.');
|
|
// Uncomment to auto-enable 3D interactivity once scene loads:
|
|
// enableSpline();
|
|
});
|
|
}
|
|
}
|
|
|
|
/* ── Navbar Scroll Effect ─────────────────────────────────────────
|
|
Adds a frosted-glass background when the user scrolls down.
|
|
─────────────────────────────────────────────────────────────── */
|
|
const navbar = document.querySelector('.navbar');
|
|
|
|
function handleNavbarScroll() {
|
|
if (!navbar) return;
|
|
if (window.scrollY > 20) {
|
|
navbar.style.background = 'rgba(0, 0, 0, 0.55)';
|
|
navbar.style.backdropFilter = 'blur(16px)';
|
|
navbar.style.webkitBackdropFilter = 'blur(16px)';
|
|
} else {
|
|
navbar.style.background = 'transparent';
|
|
navbar.style.backdropFilter = 'none';
|
|
navbar.style.webkitBackdropFilter = 'none';
|
|
}
|
|
}
|
|
|
|
window.addEventListener('scroll', handleNavbarScroll, { passive: true });
|
|
handleNavbarScroll(); // run immediately on load
|
|
|
|
/* ── Video Autoplay Fallback ──────────────────────────────────────
|
|
Gracefully handles browsers that block autoplay or fail to
|
|
load the background video.
|
|
─────────────────────────────────────────────────────────────── */
|
|
const heroVideo = document.querySelector('.hero__video');
|
|
|
|
if (heroVideo) {
|
|
// Error: video failed to load — show a subtle gradient fallback
|
|
heroVideo.addEventListener('error', () => {
|
|
console.warn('[Lumerel] Background video failed to load — using fallback gradient.');
|
|
const videoWrap = document.querySelector('.hero__video-wrap');
|
|
if (videoWrap) {
|
|
videoWrap.style.background = 'radial-gradient(ellipse at 60% 40%, #0d0d1a 0%, #000 70%)';
|
|
}
|
|
});
|
|
|
|
// iOS Safari: resume playback after first user interaction
|
|
document.addEventListener('touchstart', () => {
|
|
if (heroVideo.paused) {
|
|
heroVideo.play().catch(() => {});
|
|
}
|
|
}, { once: true });
|
|
}
|
|
|
|
/* ── Waitlist Button Handlers ─────────────────────────────────────
|
|
Replace the console.log below with your modal / form logic.
|
|
─────────────────────────────────────────────────────────────── */
|
|
const waitlistButtons = document.querySelectorAll('.btn-pill');
|
|
|
|
waitlistButtons.forEach((btn) => {
|
|
btn.addEventListener('click', () => {
|
|
console.log('[Lumerel] Join Waitlist clicked — wire up your modal or form here.');
|
|
// Example: document.getElementById('waitlist-modal').showModal();
|
|
});
|
|
});
|
|
|
|
/* ── Global Helpers ───────────────────────────────────────────────
|
|
Expose utilities on window.Lumerel for console access
|
|
and integration from external scripts.
|
|
─────────────────────────────────────────────────────────────── */
|
|
window.Lumerel = {
|
|
enableSpline,
|
|
disableSpline,
|
|
version: '1.0.0',
|
|
};
|
|
|
|
console.log('[Lumerel] 3D Homepage initialised. window.Lumerel ready.');
|