Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds
Volver a colecciones
Guide28 min read

Spline

Spline is an innovative tool for creating interactive 3D scenes in the browser with easy export to React and websites.

Spline - 3D Design w Przeglądarce

Czym jest Spline?

Spline to rewolucyjne narzędzie do tworzenia interaktywnych scen 3D bezpośrednio w przeglądarce, bez potrzeby instalowania skomplikowanego oprogramowania jak Blender czy Cinema 4D. Spline demokratyzuje 3D design, pozwalając nawet osobom bez doświadczenia w 3D tworzyć imponujące, interaktywne elementy dla stron internetowych, aplikacji i prezentacji.

To co wyróżnia Spline na tle tradycyjnych narzędzi 3D to nacisk na interaktywność i web. Sceny stworzone w Spline nie są statyczne - można dodawać animacje reagujące na hover, click, scroll, a nawet ruchy kursora. Gotowy projekt eksportuje się jako embed, kod React lub link, który można natychmiast osadzić na stronie.

Spline szybko zyskał popularność wśród web developerów i designerów, którzy chcą dodać elementy 3D do swoich projektów bez nauki skomplikowanych narzędzi. Firmy takie jak Figma, Linear czy Framer używają Spline do tworzenia interaktywnych elementów na swoich stronach.

Dlaczego Spline?

Kluczowe zalety

  1. Browser-based - Działa w przeglądarce, bez instalacji
  2. No-code 3D - Twórz 3D bez znajomości programowania
  3. Interaktywność - Hover, click, scroll, keyboard events
  4. Web-native export - React, iframe, vanilla JS
  5. Real-time collaboration - Praca zespołowa w czasie rzeczywistym
  6. Physics engine - Symulacja grawitacji i kolizji
  7. PBR Materials - Realistyczne materiały
  8. Animation timeline - Keyframe animations
  9. State machines - Zaawansowane interakcje
  10. Cloud storage - Projekty w chmurze

Spline vs tradycyjne narzędzia 3D

CechaSplineBlenderThree.jsFigma
Krzywa naukiŁatwaTrudnaŚredniaBrak 3D
Browser-based✅ (runtime)
Interaktywność✅ Built-in✅ Manual
Web export✅ One-click⚠️ Dodatkowe✅ Natywny
Real-time collab
CenaFree/$9/moFreeFreeFree/$15/mo
CelWeb 3DFull 3DCode 3D2D UI

Interfejs Spline

Pasek narzędzi

Code
TEXT
┌─────────────────────────────────────────────────────────────┐
│  TOOLBAR                                                    │
├─────────────────────────────────────────────────────────────┤
│  🔲 Select     - Zaznaczanie obiektów                       │
│  ↔️ Transform  - Przesuwanie, skalowanie, obracanie         │
│  ⬜ Cube       - Tworzenie sześcianu                        │
│  ⚪ Sphere     - Tworzenie kuli                             │
│  🔵 Cylinder   - Tworzenie cylindra                         │
│  🍩 Torus      - Tworzenie torusa                           │
│  📐 Plane      - Tworzenie płaszczyzny                      │
│  ✏️ Path       - Rysowanie ścieżek                          │
│  🅰️ Text 3D    - Tekst przestrzenny                         │
│  💡 Light      - Dodawanie świateł                          │
│  📷 Camera     - Dodawanie kamer                            │
│  🎮 Events     - Dodawanie interakcji                       │
└─────────────────────────────────────────────────────────────┘

Panel właściwości

Code
TEXT
┌─────────────────────────────────────────────────────────────┐
│  PROPERTIES                                                 │
├─────────────────────────────────────────────────────────────┤
│  Transform:                                                 │
│  Position:  X [0]  Y [0]  Z [0]                            │
│  Rotation:  X [0]  Y [0]  Z [0]                            │
│  Scale:     X [1]  Y [1]  Z [1]                            │
│                                                             │
│  Material:                                                  │
│  Type: [Glass ▼]                                           │
│  Color: [#3B82F6]                                          │
│  Metalness: [0.5] ─────────────                            │
│  Roughness: [0.2] ─────                                     │
│  Opacity:   [0.8] ───────────                               │
│                                                             │
│  Events:                                                    │
│  [+ Add Event]                                              │
│  └─ On Hover → Rotate Y 45°                                │
│  └─ On Click → Scale 1.2                                   │
└─────────────────────────────────────────────────────────────┘

Modelowanie 3D

Podstawowe prymitywy

Code
JavaScript
// Dostępne prymitywy w Spline:

// Geometric Primitives
- Cube          // Sześcian, modyfikowalne wymiary
- Sphere        // Kula z kontrolą segmentów
- Cylinder      // Cylinder z radius top/bottom
- Torus         // Torus z inner/outer radius
- Cone          // Stożek
- Plane         // Płaszczyzna
- Capsule       // Kapsuła

// Advanced Shapes
- Parametric    // Kształty parametryczne
- Extrude       // Wyciągnięcie z profilu
- Lathe         // Obrót profilu
- Text 3D       // Tekst przestrzenny
- SVG           // Import i wyciągnięcie SVG

Boolean Operations

Code
TEXT
// Operacje boolean pozwalają łączyć kształty:

Union (Suma):
┌───┐
│ ■ │ + ● = ┌───●
│   │       │
└───┘       └───┘

Subtract (Różnica):
┌───┐
│ ■ │ - ● = ┌───╮
│   │       │   ╰──
└───┘       └───┘

Intersect (Część wspólna):
┌───┐
│ ■ │ ∩ ● =   ╭──╮
│   │         │  │
└───┘         ╰──╯

Sculpting & Deformation

Code
TEXT
// Narzędzia deformacji:

Bend      - Wyginanie obiektu
Twist     - Skręcanie wzdłuż osi
Taper     - Zwężanie/rozszerzanie
Noise     - Dodawanie szumu do powierzchni
Subdivide - Zwiększenie geometrii
Smooth    - Wygładzanie krawędzi

Materiały i tekstury

PBR Materials

Spline używa fizycznie poprawnego renderowania (PBR):

Code
JavaScript
// Właściwości materiałów PBR:

Material Properties:
├── Base Color     // Kolor bazowy
├── Metalness      // 0 (dielektryk) - 1 (metal)
├── Roughness      // 0 (lustro) - 1 (matowy)
├── Normal Map     // Szczegóły powierzchni
├── Emissive       // Emisja światła
├── Opacity        // Przezroczystość
└── Refraction     // Załamanie światła

// Presety materiałów:
- Glass       // Szkło przezroczyste
- Metal       // Metaliczny połysk
- Plastic     // Plastik
- Ceramic     // Ceramika
- Rubber      // Guma
- Wood        // Drewno
- Fabric      // Tkanina

Custom Shaders

Code
JavaScript
// Spline pozwala na custom shaders:

Gradient Material:
- Start Color: #3B82F6
- End Color: #8B5CF6
- Direction: Y (vertical)

Fresnel Effect:
- Base Color: #1E40AF
- Fresnel Color: #60A5FA
- Fresnel Power: 3.0

Matcap:
- Wybierz z biblioteki matcaps
- Idealne dla stylizowanych renderów

Oświetlenie

Code
JavaScript
// Typy świateł:

Directional Light:
- Równoległe promienie (słońce)
- Shadows: Soft/Hard/None

Point Light:
- Źródło punktowe
- Range, Intensity

Spot Light:
- Stożek światła
- Angle, Penumbra

Area Light:
- Światło powierzchniowe
- Size, Softness

Ambient Light:
- Globalne oświetlenie
- Intensity, Color

HDRI Environment:
- Import obrazów HDRI
- Realistyczne odbicia

Animacje

State-based Animations

Code
JavaScript
// Stany (States) to kluczowa funkcja Spline:

Base State (default):
├── Position: (0, 0, 0)
├── Rotation: (0, 0, 0)
└── Scale: (1, 1, 1)

Hover State:
├── Position: (0, 0.5, 0)  // Unosi się
├── Rotation: (0, 15, 0)   // Obraca
└── Scale: (1.1, 1.1, 1.1) // Powiększa

Click State:
├── Position: (0, 0, 0)
├── Rotation: (0, 180, 0)  // Pełny obrót
└── Scale: (0.9, 0.9, 0.9) // Zmniejsza

// Transition settings:
- Duration: 0.3s
- Easing: ease-out
- Delay: 0s

Timeline Animations

Code
JavaScript
// Keyframe animations na timeline:

Timeline:
0s ────────── 1s ────────── 2s ────────── 3s
│             │             │             │
├── Keyframe  ├── Keyframe  ├── Keyframe  ├── Loop
Pos(0,0,0)Pos(0,2,0)Pos(0,0,0)Rot(0°)Rot(180°)Rot(360°)
// Opcje:
- Loop: Play once / Loop / Ping-pong
- Easing: Linear / Ease / Bounce / etc.
- Autoplay: On scene load

Physics Animations

Code
JavaScript
// Wbudowany silnik fizyki:

Rigid Body:
├── Mass: 1.0
├── Friction: 0.5
├── Restitution: 0.3  // Odbicie
└── Gravity: -9.8

Constraints:
├── Fixed      // Zamocowany
├── Hinge      // Zawias
├── Slider     // Suwak
└── Spring     // Sprężyna

// Przykład: Ball drop
1. Create sphere
2. Add Rigid Body
3. Create plane (floor)
4. Enable collision
5. Play physics simulation

Interaktywność

Event System

Code
JavaScript
// Dostępne wydarzenia:

Mouse Events:
├── On Hover (Mouse Enter)
├── On Hover Out (Mouse Leave)
├── On Click (Mouse Down)
├── On Mouse Up
└── On Mouse Move

Scroll Events:
├── On Scroll
└── On Scroll In View

Keyboard Events:
├── On Key Down
└── On Key Up

Scene Events:
├── On Start (Scene Load)
└── On Look At (Camera focus)

// Akcje po wydarzeniu:
- Change State
- Play Animation
- Toggle Visibility
- Change Variable
- Navigate to URL
- Play Sound

Przykłady interakcji

Code
JavaScript
// Interaktywny przycisk 3D:

Object: Button3D
Events:
├── On Hover:
│   └── Change State"Hover"
- Scale: 1.05
- Color: #60A5FA
- Transition: 0.2s
├── On Click:
│   └── Change State"Pressed"
- Scale: 0.95
- Play Sound: "click.mp3"
- After 0.1s → Navigate to "/signup"
└── On Hover Out:
    └── Change State"Default"

// Rotujący produkt:
Object: ProductModel
Events:
├── On Mouse Move:
│   └── Rotate Y: mouse.x * 0.5
└── On Scroll:
    └── Camera zoom: scroll.y * 0.1

// Parallax effect:
Layer1: On Mouse Moveoffset(x*0.1, y*0.1)
Layer2: On Mouse Moveoffset(x*0.2, y*0.2)
Layer3: On Mouse Moveoffset(x*0.3, y*0.3)

Export do Web

React Component

Code
Bash
# Instalacja
npm install @splinetool/react-spline
# lub
pnpm add @splinetool/react-spline
TScomponents/SplineScene.tsx
TypeScript
// components/SplineScene.tsx
import Spline from '@splinetool/react-spline'
import type { Application } from '@splinetool/runtime'
import { useRef } from 'react'

export function SplineScene() {
  const splineRef = useRef<Application | null>(null)

  function onLoad(spline: Application) {
    splineRef.current = spline

    // Dostęp do obiektów w scenie
    const cube = spline.findObjectByName('Cube')
    console.log('Cube loaded:', cube)
  }

  function handleClick() {
    if (!splineRef.current) return

    // Programowa interakcja
    const button = splineRef.current.findObjectByName('Button')
    if (button) {
      button.emitEvent('mouseDown')
    }
  }

  return (
    <div className="h-screen w-full">
      <Spline
        scene="https://prod.spline.design/xxxxx/scene.splinecode"
        onLoad={onLoad}
      />
      <button onClick={handleClick}>
        Trigger 3D Button
      </button>
    </div>
  )
}

Next.js Integration

TSapp/page.tsx
TypeScript
// app/page.tsx
'use client'

import dynamic from 'next/dynamic'

// Dynamic import dla SSR compatibility
const Spline = dynamic(
  () => import('@splinetool/react-spline'),
  {
    ssr: false,
    loading: () => (
      <div className="h-screen w-full flex items-center justify-center">
        <div className="animate-spin rounded-full h-12 w-12 border-t-2 border-primary" />
      </div>
    )
  }
)

export default function Home() {
  return (
    <main className="relative">
      {/* Hero z 3D */}
      <section className="h-screen relative">
        <div className="absolute inset-0 z-0">
          <Spline scene="https://prod.spline.design/hero/scene.splinecode" />
        </div>

        <div className="relative z-10 flex items-center justify-center h-full">
          <div className="text-center text-white">
            <h1 className="text-6xl font-bold mb-4">
              Welcome to the Future
            </h1>
            <p className="text-xl">
              Interactive 3D experiences for the web
            </p>
          </div>
        </div>
      </section>
    </main>
  )
}

Vanilla JavaScript

Code
HTML
<!DOCTYPE html>
<html>
<head>
  <title>Spline Scene</title>
  <style>
    #canvas3d {
      width: 100%;
      height: 100vh;
    }
  </style>
</head>
<body>
  <canvas id="canvas3d"></canvas>

  <script type="module">
    import { Application } from '@splinetool/runtime'

    const canvas = document.getElementById('canvas3d')
    const app = new Application(canvas)

    app.load('https://prod.spline.design/xxxxx/scene.splinecode')
      .then(() => {
        console.log('Scene loaded!')

        // Znajdź obiekt po nazwie
        const cube = app.findObjectByName('Cube')

        // Nasłuchuj na eventy
        cube.addEventListener('mouseDown', () => {
          console.log('Cube clicked!')
        })

        // Animuj programowo
        function animate() {
          cube.rotation.y += 0.01
          requestAnimationFrame(animate)
        }
        animate()
      })
  </script>
</body>
</html>

Iframe Embed

Code
HTML
<!-- Najprostszy sposób osadzenia -->
<iframe
  src="https://my.spline.design/untitled-xxxxx/"
  frameborder="0"
  width="100%"
  height="500px"
  allowfullscreen
></iframe>

<!-- Responsive iframe -->
<div style="position: relative; padding-bottom: 56.25%; height: 0;">
  <iframe
    src="https://my.spline.design/untitled-xxxxx/"
    style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
    frameborder="0"
    allowfullscreen
  ></iframe>
</div>

API Programistyczne

Code
TypeScript
// Spline Runtime API

interface SplineApplication {
  // Scena
  load(url: string): Promise<void>

  // Znajdowanie obiektów
  findObjectByName(name: string): SplineObject | undefined
  findObjectById(id: string): SplineObject | undefined
  getAllObjects(): SplineObject[]

  // Eventy
  addEventListener(event: string, callback: Function): void
  removeEventListener(event: string, callback: Function): void

  // Kontrola
  play(): void
  pause(): void
  setZoom(level: number): void

  // Zmienne
  setVariable(name: string, value: any): void
  getVariable(name: string): any
}

interface SplineObject {
  // Transformacje
  position: { x: number; y: number; z: number }
  rotation: { x: number; y: number; z: number }
  scale: { x: number; y: number; z: number }

  // Widoczność
  visible: boolean

  // Eventy
  emitEvent(eventType: string): void
  addEventListener(event: string, callback: Function): void

  // Dzieci
  children: SplineObject[]
  parent: SplineObject | null
}

Use Cases

Hero Sections z 3D

TScomponents/Hero3D.tsx
TypeScript
// components/Hero3D.tsx
export function Hero3D() {
  return (
    <section className="relative h-screen overflow-hidden">
      {/* 3D Background */}
      <div className="absolute inset-0">
        <Spline
          scene="https://prod.spline.design/abstract-shapes/scene.splinecode"
          style={{ width: '100%', height: '100%' }}
        />
      </div>

      {/* Gradient overlay */}
      <div className="absolute inset-0 bg-gradient-to-t from-black/80 to-transparent" />

      {/* Content */}
      <div className="relative z-10 flex items-center justify-center h-full">
        <div className="text-center text-white max-w-3xl px-4">
          <h1 className="text-5xl md:text-7xl font-bold mb-6">
            3D Made Easy
          </h1>
          <p className="text-xl mb-8 text-white/80">
            Create stunning interactive 3D experiences without code
          </p>
          <button className="bg-white text-black px-8 py-4 rounded-full font-semibold hover:scale-105 transition">
            Get Started Free
          </button>
        </div>
      </div>
    </section>
  )
}

Product Showcase

TScomponents/ProductShowcase.tsx
TypeScript
// components/ProductShowcase.tsx
import Spline from '@splinetool/react-spline'
import { useState } from 'react'

const colors = [
  { name: 'Black', value: '#000000' },
  { name: 'Silver', value: '#C0C0C0' },
  { name: 'Gold', value: '#FFD700' },
]

export function ProductShowcase() {
  const [selectedColor, setSelectedColor] = useState(colors[0])
  const [spline, setSpline] = useState<Application | null>(null)

  function onLoad(app: Application) {
    setSpline(app)
  }

  function changeColor(color: typeof colors[0]) {
    setSelectedColor(color)
    if (spline) {
      spline.setVariable('productColor', color.value)
    }
  }

  return (
    <section className="py-20 bg-gray-50">
      <div className="container mx-auto px-4">
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
          {/* 3D Model */}
          <div className="h-[500px] bg-white rounded-2xl shadow-lg overflow-hidden">
            <Spline
              scene="https://prod.spline.design/product/scene.splinecode"
              onLoad={onLoad}
            />
          </div>

          {/* Product Info */}
          <div>
            <span className="text-primary font-semibold">New Arrival</span>
            <h2 className="text-4xl font-bold mt-2 mb-4">
              Premium Headphones
            </h2>
            <p className="text-gray-600 mb-8">
              Experience crystal-clear audio with our flagship headphones.
              Drag to rotate the 3D model.
            </p>

            {/* Color Selector */}
            <div className="mb-8">
              <span className="text-sm font-medium text-gray-500">
                Color: {selectedColor.name}
              </span>
              <div className="flex gap-3 mt-2">
                {colors.map((color) => (
                  <button
                    key={color.name}
                    onClick={() => changeColor(color)}
                    className={`w-10 h-10 rounded-full border-2 transition ${
                      selectedColor.name === color.name
                        ? 'border-primary scale-110'
                        : 'border-transparent'
                    }`}
                    style={{ backgroundColor: color.value }}
                  />
                ))}
              </div>
            </div>

            <div className="flex items-center gap-4">
              <span className="text-3xl font-bold">$349</span>
              <button className="bg-primary text-white px-8 py-3 rounded-lg hover:bg-primary/90 transition">
                Add to Cart
              </button>
            </div>
          </div>
        </div>
      </div>
    </section>
  )
}

Interactive Logo

TScomponents/InteractiveLogo.tsx
TypeScript
// components/InteractiveLogo.tsx
export function InteractiveLogo() {
  return (
    <div className="w-48 h-48 cursor-pointer">
      <Spline
        scene="https://prod.spline.design/logo/scene.splinecode"
        // Logo reaguje na hover i click automatycznie
        // dzięki events zdefiniowanym w Spline
      />
    </div>
  )
}

Data Visualization

TScomponents/DataViz3D.tsx
TypeScript
// components/DataViz3D.tsx
import { useEffect, useRef } from 'react'

interface DataPoint {
  label: string
  value: number
}

export function DataViz3D({ data }: { data: DataPoint[] }) {
  const splineRef = useRef<Application | null>(null)

  useEffect(() => {
    if (!splineRef.current) return

    // Aktualizuj wysokości słupków w 3D
    data.forEach((point, index) => {
      const bar = splineRef.current?.findObjectByName(`bar_${index}`)
      if (bar) {
        bar.scale.y = point.value / 100
      }
    })
  }, [data])

  return (
    <div className="h-[400px] bg-gray-900 rounded-xl">
      <Spline
        scene="https://prod.spline.design/chart/scene.splinecode"
        onLoad={(app) => { splineRef.current = app }}
      />
    </div>
  )
}

Optymalizacja wydajności

Best Practices

Code
JavaScript
// Optymalizacja scen Spline:

// 1. Geometria
- Używaj low-poly gdzie możliwe
- Limit vertices: < 100k dla mobile
- Merge static objects
- Use instances for repeated objects

// 2. Materiały
- Ogranicz unique materials
- Unikaj heavy shaders na mobile
- Compress textures (max 2048px)
- Use matcaps zamiast PBR gdzie możliwe

// 3. Lighting
- Max 3-4 światła na scenę
- Baked lighting dla static scenes
- Disable shadows na mobile

// 4. Animacje
- Ogranicz physics objects
- Use CSS transforms gdzie możliwe
- Pausuj animacje poza viewport

// 5. Loading
- Lazy load Spline components
- Show loading placeholder
- Preload critical scenes

Lazy Loading w React

TScomponents/LazySpline.tsx
TypeScript
// components/LazySpline.tsx
import { useInView } from 'react-intersection-observer'
import dynamic from 'next/dynamic'

const Spline = dynamic(() => import('@splinetool/react-spline'), {
  ssr: false,
})

export function LazySpline({ scene }: { scene: string }) {
  const { ref, inView } = useInView({
    triggerOnce: true,
    rootMargin: '200px',
  })

  return (
    <div ref={ref} className="h-[500px]">
      {inView ? (
        <Spline scene={scene} />
      ) : (
        <div className="h-full bg-gray-100 animate-pulse rounded-xl" />
      )}
    </div>
  )
}

Cennik

PlanCenaZawiera
Free$0Unlimited projekty, Spline watermark, Public scenes
Pro$9/moNo watermark, Private scenes, Priority export
Team$29/user/moCollaboration, Shared libraries, Admin controls
EnterpriseCustomSSO, Dedicated support, Custom features

FAQ - Najczęściej zadawane pytania

Czy Spline jest darmowy?

Tak, darmowy plan pozwala na unlimited projekty i eksport. Jedynym ograniczeniem jest watermark i publiczność scen.

Czy potrzebuję umiejętności 3D?

Nie, Spline jest zaprojektowany dla osób bez doświadczenia w 3D. Interface jest intuicyjny, podobny do narzędzi 2D jak Figma.

Jak dobrze działa na mobile?

Sceny Spline działają na mobile, ale wymagają optymalizacji. Zalecana jest niska liczba polygonów i uproszczone materiały.

Czy mogę eksportować do plików 3D?

Tak, Spline pozwala na eksport do GLTF/GLB, który można użyć w innych aplikacjach 3D lub Three.js.

Jak współpracować z zespołem?

Plan Team pozwala na real-time collaboration, podobnie jak w Figma. Wielu użytkowników może edytować tę samą scenę.

Czy Spline używa WebGL?

Tak, Spline używa WebGL do renderowania. Działa we wszystkich nowoczesnych przeglądarkach.

Podsumowanie

Spline rewolucjonizuje 3D design dla web:

  • Browser-based - Twórz 3D bez instalacji
  • No-code friendly - Intuicyjny interface
  • Interaktywność - Hover, click, scroll events
  • Web-native - React, iframe, vanilla JS export
  • Real-time collaboration - Praca zespołowa
  • Physics engine - Symulacje grawitacji i kolizji

Spline to idealne narzędzie dla web developerów i designerów, którzy chcą dodać interaktywne elementy 3D do swoich projektów bez nauki skomplikowanego oprogramowania.


Spline - 3D design in the browser

What is Spline?

Spline is a revolutionary tool for creating interactive 3D scenes directly in the browser, without needing to install complex software like Blender or Cinema 4D. Spline democratizes 3D design, allowing even people with no 3D experience to create impressive, interactive elements for websites, applications, and presentations.

What sets Spline apart from traditional 3D tools is its focus on interactivity and the web. Scenes created in Spline are not static - you can add animations that respond to hover, click, scroll, and even cursor movement. The finished project can be exported as an embed, React code, or a link that can be immediately embedded on a page.

Spline quickly gained popularity among web developers and designers who want to add 3D elements to their projects without learning complex tools. Companies like Figma, Linear, and Framer use Spline to create interactive elements on their websites.

Why Spline?

Key advantages

  1. Browser-based - Works in the browser, no installation needed
  2. No-code 3D - Create 3D without programming knowledge
  3. Interactivity - Hover, click, scroll, keyboard events
  4. Web-native export - React, iframe, vanilla JS
  5. Real-time collaboration - Teamwork in real time
  6. Physics engine - Gravity and collision simulation
  7. PBR Materials - Realistic materials
  8. Animation timeline - Keyframe animations
  9. State machines - Advanced interactions
  10. Cloud storage - Projects in the cloud

Spline vs traditional 3D tools

FeatureSplineBlenderThree.jsFigma
Learning curveEasyHardMediumNo 3D
Browser-based✅ (runtime)
Interactivity✅ Built-in✅ Manual
Web export✅ One-click⚠️ Additional✅ Native
Real-time collab
PriceFree/$9/moFreeFreeFree/$15/mo
PurposeWeb 3DFull 3DCode 3D2D UI

Spline interface

Toolbar

Code
TEXT
┌─────────────────────────────────────────────────────────────┐
│  TOOLBAR                                                    │
├─────────────────────────────────────────────────────────────┤
│  🔲 Select     - Select objects                              │
│  ↔️ Transform  - Move, scale, rotate                         │
│  ⬜ Cube       - Create a cube                               │
│  ⚪ Sphere     - Create a sphere                             │
│  🔵 Cylinder   - Create a cylinder                           │
│  🍩 Torus      - Create a torus                              │
│  📐 Plane      - Create a plane                              │
│  ✏️ Path       - Draw paths                                  │
│  🅰️ Text 3D    - 3D text                                     │
│  💡 Light      - Add lights                                  │
│  📷 Camera     - Add cameras                                 │
│  🎮 Events     - Add interactions                            │
└─────────────────────────────────────────────────────────────┘

Properties panel

Code
TEXT
┌─────────────────────────────────────────────────────────────┐
│  PROPERTIES                                                 │
├─────────────────────────────────────────────────────────────┤
│  Transform:                                                 │
│  Position:  X [0]  Y [0]  Z [0]                            │
│  Rotation:  X [0]  Y [0]  Z [0]                            │
│  Scale:     X [1]  Y [1]  Z [1]                            │
│                                                             │
│  Material:                                                  │
│  Type: [Glass ▼]                                           │
│  Color: [#3B82F6]                                          │
│  Metalness: [0.5] ─────────────                            │
│  Roughness: [0.2] ─────                                     │
│  Opacity:   [0.8] ───────────                               │
│                                                             │
│  Events:                                                    │
│  [+ Add Event]                                              │
│  └─ On Hover → Rotate Y 45°                                │
│  └─ On Click → Scale 1.2                                   │
└─────────────────────────────────────────────────────────────┘

3D modeling

Basic primitives

Code
JavaScript
// Available primitives in Spline:

// Geometric Primitives
- Cube          // Cube with modifiable dimensions
- Sphere        // Sphere with segment control
- Cylinder      // Cylinder with radius top/bottom
- Torus         // Torus with inner/outer radius
- Cone          // Cone
- Plane         // Plane
- Capsule       // Capsule

// Advanced Shapes
- Parametric    // Parametric shapes
- Extrude       // Extrusion from a profile
- Lathe         // Profile revolution
- Text 3D       // 3D text
- SVG           // Import and extrude SVG

Boolean operations

Code
TEXT
// Boolean operations allow you to combine shapes:

Union (Sum):
┌───┐
│ ■ │ + ● = ┌───●
│   │       │
└───┘       └───┘

Subtract (Difference):
┌───┐
│ ■ │ - ● = ┌───╮
│   │       │   ╰──
└───┘       └───┘

Intersect (Intersection):
┌───┐
│ ■ │ ∩ ● =   ╭──╮
│   │         │  │
└───┘         ╰──╯

Sculpting & deformation

Code
TEXT
// Deformation tools:

Bend      - Bending an object
Twist     - Twisting along an axis
Taper     - Narrowing/widening
Noise     - Adding noise to a surface
Subdivide - Increasing geometry
Smooth    - Smoothing edges

Materials and textures

PBR materials

Spline uses physically based rendering (PBR):

Code
JavaScript
// PBR material properties:

Material Properties:
├── Base Color     // Base color
├── Metalness      // 0 (dielectric) - 1 (metal)
├── Roughness      // 0 (mirror) - 1 (matte)
├── Normal Map     // Surface details
├── Emissive       // Light emission
├── Opacity        // Transparency
└── Refraction     // Light refraction

// Material presets:
- Glass       // Transparent glass
- Metal       // Metallic shine
- Plastic     // Plastic
- Ceramic     // Ceramic
- Rubber      // Rubber
- Wood        // Wood
- Fabric      // Fabric

Custom shaders

Code
JavaScript
// Spline allows custom shaders:

Gradient Material:
- Start Color: #3B82F6
- End Color: #8B5CF6
- Direction: Y (vertical)

Fresnel Effect:
- Base Color: #1E40AF
- Fresnel Color: #60A5FA
- Fresnel Power: 3.0

Matcap:
- Choose from the matcap library
- Ideal for stylized renders

Lighting

Code
JavaScript
// Light types:

Directional Light:
- Parallel rays (sun)
- Shadows: Soft/Hard/None

Point Light:
- Point source
- Range, Intensity

Spot Light:
- Light cone
- Angle, Penumbra

Area Light:
- Surface light
- Size, Softness

Ambient Light:
- Global illumination
- Intensity, Color

HDRI Environment:
- Import HDRI images
- Realistic reflections

Animations

State-based animations

Code
JavaScript
// States are a key feature of Spline:

Base State (default):
├── Position: (0, 0, 0)
├── Rotation: (0, 0, 0)
└── Scale: (1, 1, 1)

Hover State:
├── Position: (0, 0.5, 0)  // Floats up
├── Rotation: (0, 15, 0)   // Rotates
└── Scale: (1.1, 1.1, 1.1) // Scales up

Click State:
├── Position: (0, 0, 0)
├── Rotation: (0, 180, 0)  // Full rotation
└── Scale: (0.9, 0.9, 0.9) // Scales down

// Transition settings:
- Duration: 0.3s
- Easing: ease-out
- Delay: 0s

Timeline animations

Code
JavaScript
// Keyframe animations on the timeline:

Timeline:
0s ────────── 1s ────────── 2s ────────── 3s
│             │             │             │
├── Keyframe  ├── Keyframe  ├── Keyframe  ├── Loop
Pos(0,0,0)Pos(0,2,0)Pos(0,0,0)Rot(0°)Rot(180°)Rot(360°)
// Options:
- Loop: Play once / Loop / Ping-pong
- Easing: Linear / Ease / Bounce / etc.
- Autoplay: On scene load

Physics animations

Code
JavaScript
// Built-in physics engine:

Rigid Body:
├── Mass: 1.0
├── Friction: 0.5
├── Restitution: 0.3  // Bounce
└── Gravity: -9.8

Constraints:
├── Fixed      // Fixed in place
├── Hinge      // Hinge joint
├── Slider     // Slider joint
└── Spring     // Spring joint

// Example: Ball drop
1. Create sphere
2. Add Rigid Body
3. Create plane (floor)
4. Enable collision
5. Play physics simulation

Interactivity

Event system

Code
JavaScript
// Available events:

Mouse Events:
├── On Hover (Mouse Enter)
├── On Hover Out (Mouse Leave)
├── On Click (Mouse Down)
├── On Mouse Up
└── On Mouse Move

Scroll Events:
├── On Scroll
└── On Scroll In View

Keyboard Events:
├── On Key Down
└── On Key Up

Scene Events:
├── On Start (Scene Load)
└── On Look At (Camera focus)

// Actions after an event:
- Change State
- Play Animation
- Toggle Visibility
- Change Variable
- Navigate to URL
- Play Sound

Interaction examples

Code
JavaScript
// Interactive 3D button:

Object: Button3D
Events:
├── On Hover:
│   └── Change State"Hover"
- Scale: 1.05
- Color: #60A5FA
- Transition: 0.2s
├── On Click:
│   └── Change State"Pressed"
- Scale: 0.95
- Play Sound: "click.mp3"
- After 0.1s → Navigate to "/signup"
└── On Hover Out:
    └── Change State"Default"

// Rotating product:
Object: ProductModel
Events:
├── On Mouse Move:
│   └── Rotate Y: mouse.x * 0.5
└── On Scroll:
    └── Camera zoom: scroll.y * 0.1

// Parallax effect:
Layer1: On Mouse Moveoffset(x*0.1, y*0.1)
Layer2: On Mouse Moveoffset(x*0.2, y*0.2)
Layer3: On Mouse Moveoffset(x*0.3, y*0.3)

Export to web

React component

Code
Bash
# Installation
npm install @splinetool/react-spline
# or
pnpm add @splinetool/react-spline
TScomponents/SplineScene.tsx
TypeScript
// components/SplineScene.tsx
import Spline from '@splinetool/react-spline'
import type { Application } from '@splinetool/runtime'
import { useRef } from 'react'

export function SplineScene() {
  const splineRef = useRef<Application | null>(null)

  function onLoad(spline: Application) {
    splineRef.current = spline

    const cube = spline.findObjectByName('Cube')
    console.log('Cube loaded:', cube)
  }

  function handleClick() {
    if (!splineRef.current) return

    const button = splineRef.current.findObjectByName('Button')
    if (button) {
      button.emitEvent('mouseDown')
    }
  }

  return (
    <div className="h-screen w-full">
      <Spline
        scene="https://prod.spline.design/xxxxx/scene.splinecode"
        onLoad={onLoad}
      />
      <button onClick={handleClick}>
        Trigger 3D Button
      </button>
    </div>
  )
}

Next.js integration

TSapp/page.tsx
TypeScript
// app/page.tsx
'use client'

import dynamic from 'next/dynamic'

const Spline = dynamic(
  () => import('@splinetool/react-spline'),
  {
    ssr: false,
    loading: () => (
      <div className="h-screen w-full flex items-center justify-center">
        <div className="animate-spin rounded-full h-12 w-12 border-t-2 border-primary" />
      </div>
    )
  }
)

export default function Home() {
  return (
    <main className="relative">
      {/* Hero with 3D */}
      <section className="h-screen relative">
        <div className="absolute inset-0 z-0">
          <Spline scene="https://prod.spline.design/hero/scene.splinecode" />
        </div>

        <div className="relative z-10 flex items-center justify-center h-full">
          <div className="text-center text-white">
            <h1 className="text-6xl font-bold mb-4">
              Welcome to the Future
            </h1>
            <p className="text-xl">
              Interactive 3D experiences for the web
            </p>
          </div>
        </div>
      </section>
    </main>
  )
}

Vanilla JavaScript

Code
HTML
<!DOCTYPE html>
<html>
<head>
  <title>Spline Scene</title>
  <style>
    #canvas3d {
      width: 100%;
      height: 100vh;
    }
  </style>
</head>
<body>
  <canvas id="canvas3d"></canvas>

  <script type="module">
    import { Application } from '@splinetool/runtime'

    const canvas = document.getElementById('canvas3d')
    const app = new Application(canvas)

    app.load('https://prod.spline.design/xxxxx/scene.splinecode')
      .then(() => {
        console.log('Scene loaded!')

        const cube = app.findObjectByName('Cube')

        cube.addEventListener('mouseDown', () => {
          console.log('Cube clicked!')
        })

        function animate() {
          cube.rotation.y += 0.01
          requestAnimationFrame(animate)
        }
        animate()
      })
  </script>
</body>
</html>

Iframe embed

Code
HTML
<!-- Simplest way to embed -->
<iframe
  src="https://my.spline.design/untitled-xxxxx/"
  frameborder="0"
  width="100%"
  height="500px"
  allowfullscreen
></iframe>

<!-- Responsive iframe -->
<div style="position: relative; padding-bottom: 56.25%; height: 0;">
  <iframe
    src="https://my.spline.design/untitled-xxxxx/"
    style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
    frameborder="0"
    allowfullscreen
  ></iframe>
</div>

Programming API

Code
TypeScript
// Spline Runtime API

interface SplineApplication {
  // Scene
  load(url: string): Promise<void>

  // Finding objects
  findObjectByName(name: string): SplineObject | undefined
  findObjectById(id: string): SplineObject | undefined
  getAllObjects(): SplineObject[]

  // Events
  addEventListener(event: string, callback: Function): void
  removeEventListener(event: string, callback: Function): void

  // Control
  play(): void
  pause(): void
  setZoom(level: number): void

  // Variables
  setVariable(name: string, value: any): void
  getVariable(name: string): any
}

interface SplineObject {
  // Transforms
  position: { x: number; y: number; z: number }
  rotation: { x: number; y: number; z: number }
  scale: { x: number; y: number; z: number }

  // Visibility
  visible: boolean

  // Events
  emitEvent(eventType: string): void
  addEventListener(event: string, callback: Function): void

  // Children
  children: SplineObject[]
  parent: SplineObject | null
}

Use cases

Hero sections with 3D

TScomponents/Hero3D.tsx
TypeScript
// components/Hero3D.tsx
export function Hero3D() {
  return (
    <section className="relative h-screen overflow-hidden">
      {/* 3D Background */}
      <div className="absolute inset-0">
        <Spline
          scene="https://prod.spline.design/abstract-shapes/scene.splinecode"
          style={{ width: '100%', height: '100%' }}
        />
      </div>

      {/* Gradient overlay */}
      <div className="absolute inset-0 bg-gradient-to-t from-black/80 to-transparent" />

      {/* Content */}
      <div className="relative z-10 flex items-center justify-center h-full">
        <div className="text-center text-white max-w-3xl px-4">
          <h1 className="text-5xl md:text-7xl font-bold mb-6">
            3D Made Easy
          </h1>
          <p className="text-xl mb-8 text-white/80">
            Create stunning interactive 3D experiences without code
          </p>
          <button className="bg-white text-black px-8 py-4 rounded-full font-semibold hover:scale-105 transition">
            Get Started Free
          </button>
        </div>
      </div>
    </section>
  )
}

Product showcase

TScomponents/ProductShowcase.tsx
TypeScript
// components/ProductShowcase.tsx
import Spline from '@splinetool/react-spline'
import { useState } from 'react'

const colors = [
  { name: 'Black', value: '#000000' },
  { name: 'Silver', value: '#C0C0C0' },
  { name: 'Gold', value: '#FFD700' },
]

export function ProductShowcase() {
  const [selectedColor, setSelectedColor] = useState(colors[0])
  const [spline, setSpline] = useState<Application | null>(null)

  function onLoad(app: Application) {
    setSpline(app)
  }

  function changeColor(color: typeof colors[0]) {
    setSelectedColor(color)
    if (spline) {
      spline.setVariable('productColor', color.value)
    }
  }

  return (
    <section className="py-20 bg-gray-50">
      <div className="container mx-auto px-4">
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
          {/* 3D Model */}
          <div className="h-[500px] bg-white rounded-2xl shadow-lg overflow-hidden">
            <Spline
              scene="https://prod.spline.design/product/scene.splinecode"
              onLoad={onLoad}
            />
          </div>

          {/* Product Info */}
          <div>
            <span className="text-primary font-semibold">New Arrival</span>
            <h2 className="text-4xl font-bold mt-2 mb-4">
              Premium Headphones
            </h2>
            <p className="text-gray-600 mb-8">
              Experience crystal-clear audio with our flagship headphones.
              Drag to rotate the 3D model.
            </p>

            {/* Color Selector */}
            <div className="mb-8">
              <span className="text-sm font-medium text-gray-500">
                Color: {selectedColor.name}
              </span>
              <div className="flex gap-3 mt-2">
                {colors.map((color) => (
                  <button
                    key={color.name}
                    onClick={() => changeColor(color)}
                    className={`w-10 h-10 rounded-full border-2 transition ${
                      selectedColor.name === color.name
                        ? 'border-primary scale-110'
                        : 'border-transparent'
                    }`}
                    style={{ backgroundColor: color.value }}
                  />
                ))}
              </div>
            </div>

            <div className="flex items-center gap-4">
              <span className="text-3xl font-bold">$349</span>
              <button className="bg-primary text-white px-8 py-3 rounded-lg hover:bg-primary/90 transition">
                Add to Cart
              </button>
            </div>
          </div>
        </div>
      </div>
    </section>
  )
}

Interactive logo

TScomponents/InteractiveLogo.tsx
TypeScript
// components/InteractiveLogo.tsx
export function InteractiveLogo() {
  return (
    <div className="w-48 h-48 cursor-pointer">
      <Spline
        scene="https://prod.spline.design/logo/scene.splinecode"
      />
    </div>
  )
}

Data visualization

TScomponents/DataViz3D.tsx
TypeScript
// components/DataViz3D.tsx
import { useEffect, useRef } from 'react'

interface DataPoint {
  label: string
  value: number
}

export function DataViz3D({ data }: { data: DataPoint[] }) {
  const splineRef = useRef<Application | null>(null)

  useEffect(() => {
    if (!splineRef.current) return

    data.forEach((point, index) => {
      const bar = splineRef.current?.findObjectByName(`bar_${index}`)
      if (bar) {
        bar.scale.y = point.value / 100
      }
    })
  }, [data])

  return (
    <div className="h-[400px] bg-gray-900 rounded-xl">
      <Spline
        scene="https://prod.spline.design/chart/scene.splinecode"
        onLoad={(app) => { splineRef.current = app }}
      />
    </div>
  )
}

Performance optimization

Best practices

Code
JavaScript
// Optimizing Spline scenes:

// 1. Geometry
- Use low-poly where possible
- Limit vertices: < 100k for mobile
- Merge static objects
- Use instances for repeated objects

// 2. Materials
- Limit unique materials
- Avoid heavy shaders on mobile
- Compress textures (max 2048px)
- Use matcaps instead of PBR where possible

// 3. Lighting
- Max 3-4 lights per scene
- Baked lighting for static scenes
- Disable shadows on mobile

// 4. Animations
- Limit physics objects
- Use CSS transforms where possible
- Pause animations outside the viewport

// 5. Loading
- Lazy load Spline components
- Show loading placeholder
- Preload critical scenes

Lazy loading in React

TScomponents/LazySpline.tsx
TypeScript
// components/LazySpline.tsx
import { useInView } from 'react-intersection-observer'
import dynamic from 'next/dynamic'

const Spline = dynamic(() => import('@splinetool/react-spline'), {
  ssr: false,
})

export function LazySpline({ scene }: { scene: string }) {
  const { ref, inView } = useInView({
    triggerOnce: true,
    rootMargin: '200px',
  })

  return (
    <div ref={ref} className="h-[500px]">
      {inView ? (
        <Spline scene={scene} />
      ) : (
        <div className="h-full bg-gray-100 animate-pulse rounded-xl" />
      )}
    </div>
  )
}

Pricing

PlanPriceIncludes
Free$0Unlimited projects, Spline watermark, Public scenes
Pro$9/moNo watermark, Private scenes, Priority export
Team$29/user/moCollaboration, Shared libraries, Admin controls
EnterpriseCustomSSO, Dedicated support, Custom features

FAQ - frequently asked questions

Is Spline free?

Yes, the free plan allows unlimited projects and export. The only limitations are the watermark and scenes being public.

Do I need 3D skills?

No, Spline is designed for people with no 3D experience. The interface is intuitive, similar to 2D tools like Figma.

How well does it work on mobile?

Spline scenes work on mobile, but they require optimization. A low polygon count and simplified materials are recommended.

Can I export to 3D files?

Yes, Spline allows export to GLTF/GLB, which can be used in other 3D applications or Three.js.

How do I collaborate with a team?

The Team plan enables real-time collaboration, similar to Figma. Multiple users can edit the same scene simultaneously.

Does Spline use WebGL?

Yes, Spline uses WebGL for rendering. It works in all modern browsers.

Summary

Spline revolutionizes 3D design for the web:

  • Browser-based - Create 3D without installation
  • No-code friendly - Intuitive interface
  • Interactivity - Hover, click, scroll events
  • Web-native - React, iframe, vanilla JS export
  • Real-time collaboration - Teamwork
  • Physics engine - Gravity and collision simulations

Spline is the ideal tool for web developers and designers who want to add interactive 3D elements to their projects without learning complex software.