Interactive 3D Demo (Vanilla JS)
by Samin Sami
HTML
<!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Preload Spline runtime for faster loading -->
<link rel="preload" href="https://unpkg.com/@splinetool/runtime@1.2.6/build/runtime.js" as="script">
<main class="min-h-screen">
<div class="max-w-6xl mx-auto">
<header class="mb-12">
<h1 class="text-3xl font-bold">Interactive 3D Demo</h1>
<p class="text-gray-400 mt-2">Experience the power of Spline 3D in Vanilla JS</p>
</header>
<section class="mb-12">
<!-- Main card with 3D scene - Increased height and adjusted layout -->
<div id="spline-scene-basic-card" class="w-full h-[700px] bg-black/[0.96] relative overflow-hidden rounded-lg border border-gray-800 shadow-xl">
<!-- Spotlight effect -->
<div id="spotlight-element"
class="spotlight"
style="width: 200px; height: 200px; transition: transform 0.1s ease-out;">
</div>
<div class="flex h-full flex-col md:flex-row">
<!-- Left content - Reduced width -->
<div class="md:w-2/5 p-6 md:p-8 relative z-10 flex flex-col justify-center">
<h3 class="text-4xl md:text-5xl font-bold gradient-text">
Interactive 3D
</h3>
<p class="mt-4 text-neutral-300 max-w-md">
Bring your UI to life with beautiful 3D scenes. Create immersive experiences
that capture attention and enhance your design.
</p>
<div class="mt-6">
<button class="px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded-md transition-colors">
...
CSS
/* Custom styles for the loader */
.loader {
width: 48px;
height: 48px;
border: 5px solid #FFF;
border-bottom-color: transparent;
border-radius: 50%;
display: inline-block;
box-sizing: border-box;
animation: rotation 1s linear infinite;
}
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Additional custom styles */
.gradient-text {
background: linear-gradient(to bottom, #f8fafc, #cbd5e1);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.spotlight {
pointer-events: none;
position: absolute;
border-radius: 50%;
background: radial-gradient(circle at center, rgba(248, 250, 252, 0.8), rgba(248, 250, 252, 0.4), transparent 80%);
filter: blur(20px);
transition: opacity 0.2s ease-out;
opacity: 0;
}
JavaScript
// Initialize Spline scene as soon as possible
function initSpline() {
const splineCanvas = document.getElementById('spline-canvas');
const splineLoader = document.getElementById('spline-loader');
const splineSceneUrl = "https://prod.spline.design/kZDDjO5HuC9GJUM2/scene.splinecode";
if (!splineCanvas || !splineLoader) {
console.error('Required Spline elements not found');
return;
}
// Hide canvas and show loader initially
splineCanvas.classList.add('hidden');
splineLoader.classList.remove('hidden');
// Load Spline runtime dynamically
import('https://unpkg.com/@splinetool/runtime@1.2.6/build/runtime.js')
.then(({ Application }) => {
try {
// Initialize Spline application
const app = new Application(splineCanvas);
// Load the Spline scene
app.load(splineSceneUrl)
.then(() => {
// Hide loader and show canvas once loaded
splineLoader.classList.add('hidden');
splineCanvas.classList.remove('hidden');
console.log('Spline scene loaded successfully!');
// Initialize spotlight effect after scene loads
initSpotlight();
})
.catch(error => {
console.error('Failed to load Spline scene:', error);
splineLoader.innerHTML = '<p class="text-red-500 text-center">Failed to load 3D scene</p>';
});
} catch (error) {
...