Deploy from Lumerel
This commit is contained in:
138
main.js
Normal file
138
main.js
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* Lumerel — 3D Homepage
|
||||
* main.js
|
||||
*
|
||||
* Handles:
|
||||
* - Spline 3D scene loading & pointer-events toggle
|
||||
* - Navbar scroll behaviour (frosted glass on scroll)
|
||||
* - Video autoplay fallback (iOS)
|
||||
* - 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. If the scene needs mouse/touch interaction, uncomment the
|
||||
* enableSplinePointerEvents() call in the 'load' listener below.
|
||||
*
|
||||
* 3. Optionally import the @splinetool/runtime package directly:
|
||||
*
|
||||
* import { Application } from '@splinetool/runtime';
|
||||
* const app = new Application(document.getElementById('my-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 enableSplinePointerEvents() {
|
||||
if (splineLayer) {
|
||||
splineLayer.style.pointerEvents = 'auto';
|
||||
console.log('[Lumerel] Spline pointer events ENABLED.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable pointer events on the 3D layer (default state).
|
||||
* Ensures UI elements (buttons, links) remain fully clickable.
|
||||
*/
|
||||
function disableSplinePointerEvents() {
|
||||
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 enable 3D interactivity:
|
||||
// enableSplinePointerEvents();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* ── 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.40)';
|
||||
navbar.style.backdropFilter = 'blur(14px)';
|
||||
navbar.style.webkitBackdropFilter = 'blur(14px)';
|
||||
} else {
|
||||
navbar.style.background = 'transparent';
|
||||
navbar.style.backdropFilter = 'none';
|
||||
navbar.style.webkitBackdropFilter = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', handleNavbarScroll, { passive: true });
|
||||
handleNavbarScroll(); // run on initial load
|
||||
|
||||
/* ── Video Fallback ──────────────────────────────────────────
|
||||
Gracefully handles browsers that block autoplay or fail to
|
||||
load the background video.
|
||||
──────────────────────────────────────────────────────────────── */
|
||||
const heroVideo = document.querySelector('.hero__video');
|
||||
|
||||
if (heroVideo) {
|
||||
heroVideo.addEventListener('error', () => {
|
||||
console.warn('[Lumerel] Background video failed to load. Using fallback background.');
|
||||
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 with your modal / form integration.
|
||||
──────────────────────────────────────────────────────────────── */
|
||||
const waitlistBtns = document.querySelectorAll('.btn-pill');
|
||||
|
||||
waitlistBtns.forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
console.log('[Lumerel] Join Waitlist clicked.');
|
||||
// TODO: open waitlist modal or navigate to signup form
|
||||
// Example: openWaitlistModal();
|
||||
// Example: window.location.href = '/waitlist';
|
||||
});
|
||||
});
|
||||
|
||||
/* ── Expose helpers globally ─────────────────────────────────
|
||||
Access from DevTools console or other scripts:
|
||||
window.Lumerel.enableSplinePointerEvents()
|
||||
──────────────────────────────────────────────────────────────── */
|
||||
window.Lumerel = {
|
||||
enableSplinePointerEvents,
|
||||
disableSplinePointerEvents,
|
||||
};
|
||||
Reference in New Issue
Block a user