4.8 KiB
4.8 KiB
React / Next.js / Vue Integration
React / Vite
Install:
npm install @splinetool/react-spline
Basic:
import Spline from '@splinetool/react-spline';
export default function App() {
return (
<div style={{ width: '100%', height: '100vh' }}>
<Spline scene="https://prod.spline.design/REPLACE_ME/scene.splinecode" />
</div>
);
}
With object interaction + event listeners:
import { useRef } from 'react';
import Spline from '@splinetool/react-spline';
export default function App() {
const splineRef = useRef();
function onLoad(splineApp) {
splineRef.current = splineApp;
}
function triggerAnimation() {
splineRef.current.emitEvent('mouseHover', 'Cube');
}
function onSplineEvent(e) {
console.log('Object interacted:', e.target.name);
}
return (
<div>
<Spline
scene="https://prod.spline.design/REPLACE_ME/scene.splinecode"
onLoad={onLoad}
onMouseDown={onSplineEvent}
/>
<button onClick={triggerAnimation}>Trigger</button>
</div>
);
}
Lazy loading (recommended for performance):
import { lazy, Suspense } from 'react';
const Spline = lazy(() => import('@splinetool/react-spline'));
export default function Hero() {
return (
<Suspense fallback={<div style={{ background: '#0a0a0a', width: '100%', height: '100vh' }} />}>
<Spline scene="https://prod.spline.design/REPLACE_ME/scene.splinecode" />
</Suspense>
);
}
Next.js
Install:
npm install @splinetool/react-spline
Use the /next import for SSR support + auto blurred placeholder:
import Spline from '@splinetool/react-spline/next';
export default function Page() {
return (
<Spline scene="https://prod.spline.design/REPLACE_ME/scene.splinecode" />
);
}
With dynamic import (if you get hydration errors):
import dynamic from 'next/dynamic';
const Spline = dynamic(() => import('@splinetool/react-spline/next'), {
ssr: false,
loading: () => <div style={{ background: '#0a0a0a', width: '100%', height: '100vh' }} />
});
export default function Page() {
return <Spline scene="https://prod.spline.design/REPLACE_ME/scene.splinecode" />;
}
Vue
Install:
npm install @splinetool/vue-spline
<template>
<Spline
scene="https://prod.spline.design/REPLACE_ME/scene.splinecode"
@spline-loaded="onLoaded"
@mouseDown="onClick"
/>
</template>
<script>
import Spline from '@splinetool/vue-spline';
export default {
components: { Spline },
methods: {
onLoaded(spline) {
const obj = spline.findObjectByName('Cube');
obj.position.x += 10; // NOTE: radians for rotation, not degrees
},
onClick(e) {
console.log('Clicked:', e.target.name);
}
}
}
</script>
Full-Page Background (React)
import Spline from '@splinetool/react-spline';
import { useState } from 'react';
export default function HeroSection() {
const [loaded, setLoaded] = useState(false);
// Skip Spline on mobile / low-end devices
const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;
const isLowEnd = typeof navigator !== 'undefined' && navigator.hardwareConcurrency <= 2;
return (
<div style={{ position: 'relative', width: '100vw', height: '100vh' }}>
{/* Fallback background — always rendered, hidden once Spline loads */}
<div style={{
position: 'absolute', inset: 0,
background: '#0a0a0a',
zIndex: 0,
opacity: loaded ? 0 : 1,
transition: 'opacity 0.5s ease'
}} />
{/* Spline scene — only load on capable devices */}
{!isMobile && !isLowEnd && (
<Spline
scene="https://prod.spline.design/REPLACE_ME/scene.splinecode"
onLoad={() => setLoaded(true)}
style={{
position: 'absolute',
top: 0, left: 0,
width: '100%', height: '100%',
zIndex: 0
}}
/>
)}
{/* Content sits on top */}
<div style={{ position: 'relative', zIndex: 1 }}>
<h1>Your Content Here</h1>
</div>
</div>
);
}
React Prop Reference
| Prop | Type | Description |
|---|---|---|
scene |
string | Scene URL (required) |
onLoad |
function | Called with splineApp when loaded |
onMouseDown |
function | Mouse/touch down on object |
onMouseUp |
function | Mouse/touch up |
onMouseHover |
function | Hover over object |
onKeyDown |
function | Key pressed |
onKeyUp |
function | Key released |
onStart |
function | Scene started |
onScroll |
function | Scroll event |
style |
object | CSS styles for the canvas |
className |
string | CSS class |
See PERFORMANCE.md and COMMON_PROBLEMS.md before finishing.