React component for Spline scenes.

Overview

react-spline

react-spline allows you to export and use Spline scenes directly in your React websites.

🌈 Spline is a friendly 3d collaborative design tool for the web.

WebsiteTwitterCommunityDocumentation

Table of Contents

Install

yarn add @splinetool/react-spline @splinetool/runtime

or

npm install @splinetool/react-spline @splinetool/runtime

Usage

To use react-spline, first you have to go to the Spline editor, click on the Export button, select "Code" and then "React".

You should see this:

You can copy the URL and pass it to the <Spline /> component in react:

import Spline from '@splinetool/react-spline';

export default function App() {
  return (
    <div>
      <Spline scene="https://prod.spline.design/6Wq1Q7YGyM-iab9i/scene.splinecode" />
    </div>
  );
}

You should be able to see the scene you exported in your React app.

Read and modify Spline objects

You can query any Spline object via findObjectByName or findObjectById.

(You can get the ID of the object in the Develop pane of the right sidebar).

import { useRef } from 'react';
import Spline from '@splinetool/react-spline';

export default function App() {
  const cube = useRef();

  function onLoad(spline) {
    const obj = spline.findObjectByName('Cube');
    // or
    // const obj = spline.findObjectById('8E8C2DDD-18B6-4C54-861D-7ED2519DE20E');

    // save it in a ref for later use
    cube.current = obj;
  }

  function moveObj() {
    console.log(cube.current); // Spline Object => { name: 'Cube', id: '8E8C2DDD-18B6-4C54-861D-7ED2519DE20E', position: {}, ... }

    // move the object in 3D space
    cube.current.position.x += 10;
  }

  return (
    <div>
      <Spline
        scene="https://prod.spline.design/6Wq1Q7YGyM-iab9i/scene.splinecode"
        onLoad={onLoad}
      />
      <button type="button" onClick={moveObj}>
        Move Cube
      </button>
    </div>
  );
}

Listen to events

You can listen to any Spline Event you set in the Events panel of the editor by attaching a listener to the Spline component.

import Spline from '@splinetool/react-spline';

export default function App() {
  function onMouseDown(e) {
    if (e.target.name === 'Cube') {
      console.log('I have been clicked!');
    }
  }

  return (
    <div>
      <Spline
        scene="https://prod.spline.design/6Wq1Q7YGyM-iab9i/scene.splinecode"
        onMouseDown={onMouseDown}
      />
    </div>
  );
}

You can find a list of all of the Spline Event listeners in the Spline Component Props section.

Trigger Spline events from outside

You can trigger any animation Event you set in the Events panel in the Spline Editor.

You can use the emitEvent function via the spline ref, passing the event type and the ID of your object.

(You can get the ID of the object in the Develop pane of the right sidebar).

import { useRef } from 'react';
import Spline from '@splinetool/react-spline';

export default function App() {
  const spline = useRef();

  function onLoad(splineApp) {
    // save the app in a ref for later use
    spline.current = splineApp;
  }

  function triggerAnimation() {
    spline.current.emitEvent('mouseHover', 'Cube');
  }

  return (
    <div>
      <Spline
        scene="https://prod.spline.design/6Wq1Q7YGyM-iab9i/scene.splinecode"
        onLoad={onLoad}
      />
      <button type="button" onClick={triggerAnimation}>
        Trigger Spline Animation
      </button>
    </div>
  );
}

Or you can query the spline object first, and then trigger the event:

import { useRef } from 'react';
import Spline from '@splinetool/react-spline';

export default function App() {
  const objectToAnimate = useRef();

  function onLoad(spline) {
    const obj = spline.findObjectByName('Cube');
    // save the object in a ref for later use
    objectToAnimate.current = obj;
  }

  function triggerAnimation() {
    objectToAnimate.current.emitEvent('mouseHover');
  }

  return (
    <div>
      <Spline
        scene="https://prod.spline.design/6Wq1Q7YGyM-iab9i/scene.splinecode"
        onLoad={onLoad}
      />
      <button type="button" onClick={triggerAnimation}>
        Trigger Spline Animation
      </button>
    </div>
  );
}

You can find a list of all of the Spline Events you can pass to the emitEvent function in the Spline Events section.

Lazy loading

To start loading react-spline after the whole website has finished loading, we can use lazy-loading. This technique can be achieved using React.lazy() in combination with dynamic imports:

import React, { Suspense } from 'react';

const Spline = React.lazy(() => import('@splinetool/react-spline'));

export default function App() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <Spline scene="https://prod.spline.design/6Wq1Q7YGyM-iab9i/scene.splinecode" />
      </Suspense>
    </div>
  );
}

More info in the relative React documentation.

API

Spline Component Props

These are all the props you can pass to the <Spline /> component.

Name Type Description
scene string Scene file
onLoad? (spline: Application) => void Gets called once the scene has loaded. The spline parameter is an instance of the Spline Application
renderOnDemand? boolean Wether or not to enable on demand rendering. Default true.
className? string CSS classes
style? object CSS style
id? string Canvas id
ref? React.Ref<HTMLDivElement> A ref pointing to canvas element.
onWheel? (e: SplineEvent) => void Gets called on the wheel event on the canvas
onMouseDown? (e: SplineEvent) => void Gets called once a Spline Mouse Down event is fired
onMouseHover? (e: SplineEvent) => void Gets called once a Spline Mouse Hover event is fired
onMouseUp? (e: SplineEvent) => void Gets called once a Spline Mouse Up event is fired
onKeyDown? (e: SplineEvent) => void Gets called once a Spline Key Down event is fired
onKeyUp? (e: SplineEvent) => void Gets called once a Spline Key Up event is fired
onStart? (e: SplineEvent) => void Gets called once a Spline Start event is fired
onLookAt? (e: SplineEvent) => void Gets called once a Spline Look At event is fired
onFollow? (e: SplineEvent) => void Gets called once a Spline Mouse Up event is fired

Spline App Methods

The object exposed as a first argument of the onLoad function, is a Spline Application. You can call all these different methods on it.

Name Type Description
emitEvent (eventName: SplineEventName, nameOrUuid: string) => void Triggers a Spline event associated to an object with provided name or uuid.
emitEventReverse (eventName: SplineEventName, nameOrUuid: string) => void Triggers a Spline event associated to an object with provided uuid in reverse order. Starts from last state to first state.
findObjectById (uuid: string) => SPEObject Searches through scene's children and returns the object with that uuid.
findObjectByName (name: string) => SPEObject Searches through scene's children and returns the first object with that name.
setZoom (zoom: number) => void Sets the initial zoom of the scene.

Spline Events

These are all the Spline event types that you can pass to the emitEvent or emitEventReverse function.

Name Description
mouseDown Refers to the Spline Mouse Down event type
mouseHover Refers to the Spline Mouse Hover event type
mouseUp Refers to the Spline Mouse Up event type
keyDown Refers to the Spline Key Down event type
keyUp Refers to the Spline Key Up event type
start Refers to the Spline Start event type
lookAt Refers to the Spline Look At event type
follow Refers to the Spline Mouse Up event type

Contributing

We use yarn, install the dependencies like this:

yarn

Development

Serve the example folder at localhost:3000

yarn dev

Build Library

yarn build

Publish on npm

yarn publish
Comments
  • Some models blocked by CORS

    Some models blocked by CORS

    Example: https://codesandbox.io/s/3d-camera-forked-cg06zu?file=/src/App.js

    The example above shows 2 models, the first works fine.

    The latter spline component (the one uncommented) gives a failed to fetch response because of CORS. (see the console)

    Let me know if anything else is needed in this issue, would love to be able to use the react Spline component in my project!

    opened by ryans1224 10
  • Text doesn't work

    Text doesn't work

    I am using Spine component in react Js with next Js and I get the following errors on my browser window,

    Unhandled Runtime Error
    Error: fetch for ["http://localhost:3000/_assets/_fonts/poppins_extralight_regular.json"](http://localhost:3000/%22http://localhost:3000/_assets/_fonts/poppins_extralight_regular.json%22) responded with 404: Not Found
    Call Stack
    eval
    node_modules\@splinetool\runtime\build\runtime.js (2994:158346)
    

    and also this similar error

    Unhandled Runtime Error
    Error: fetch for ["http://localhost:3000/_assets/_fonts/roboto_regular.json"](http://localhost:3000/%22http://localhost:3000/_assets/_fonts/roboto_regular.json%22) responded with 404: Not Found
    Call Stack
    eval
    node_modules\@splinetool\runtime\build\runtime.js (2994:158346)
    

    I am using

    node version -v14.18.1
    react version- 17.0.2
    next -12.0.10
    
    opened by harisankar01 10
  • event not work..

    event not work..

     <Spline
            scene="https://prod.spline.design/6Wq1Q7YGyM-iab9i/scene.splinecode"
            onLoad={(spline: Application) => {
              cube.current = spline.findObjectByName('Cube');
            }}
            onMouseDown={onMouseDown}
            onMouseHover={(e)=>{
              console.log(e)
            }}
          />
    

    help !! mouseDown mouseHover event not trigger....

    opened by zhangdarking 9
  • [Fix] Can't resize Spline scene.

    [Fix] Can't resize Spline scene.

    As the title says, it's actually impossible but possible with a workaround here. #26 I tried that down below in the video but this is definitely not the result we want. 😓

    The canvas size reverts to full viewport width/height as soon as the viewport is slightly resized.

    Here's what it actually renders:

    https://user-images.githubusercontent.com/87608619/163722776-e7c509d1-f99e-4567-b49c-f92bb6d11396.mov

    opened by Walidoux 9
  • [Bug] Canvas size dosen't work properly with version 2.2.1

    [Bug] Canvas size dosen't work properly with version 2.2.1

    I've updated to the new version 2.2.1 and in my existing project and in the example project from the repository the canvas is sized randomly with 0x0 pixel on load. I've tested this behaviour in Chrome, Safari and Firefox and got the same result.

    https://user-images.githubusercontent.com/25156150/169344626-df4a14ce-86cc-43de-b815-5fb6ceffaf95.mp4

    .

    opened by dreamsinmotion 8
  • [Bug] Spline scene will sometimes not render in a production build of React app

    [Bug] Spline scene will sometimes not render in a production build of React app

    Environment is CRA and deployed using GitHub Pages. When you visit the site, one of two things will happen:

    1. Scene does not render (sometimes you see a flash before it goes)
    2. Scene renders after a brief delay

    Here is a post from Stack Overflow describing a similar problem: https://stackoverflow.com/questions/72244874/react-spline-bug-after-built-react-project-the-spline-content-is-gone-in-spli

    I've tried a variety of workarounds and potential solutions to no avail. Note that the issue described above is not encountered during development.

    opened by jsn-hoang 7
  • Next.Js Support

    Next.Js Support

    Hi there,

    I love Spline and would like to use it in my Next.js app. However, if I follow the instructions of a basic Next.js setup and react-spline setup, I get an error.

    Steps to Reproduce:

    1. Create Next.js App: npx [email protected]
    2. Install react-spline: npm install @splinetool/react-spline @splinetool/runtime
    3. Replace content in index.js with:
    import Spline from '@splinetool/react-spline';
    
    export default function App() {
      return (
        <div>
          <Spline scene="https://prod.spline.design/6Wq1Q7YGyM-iab9i/scene.splinecode" />
        </div>
      );
    }
    
    1. Run the app: npm run dev

    Expected Result: Seeing the default spline animation

    Actual Result:

    SyntaxError: Unexpected token '.'
        at wrapSafe (internal/modules/cjs/loader.js:915:16)
        at Module._compile (internal/modules/cjs/loader.js:963:27)
        at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
        at Module.load (internal/modules/cjs/loader.js:863:32)
        at Function.Module._load (internal/modules/cjs/loader.js:708:14)
        at Module.require (internal/modules/cjs/loader.js:887:19)
        at require (internal/modules/cjs/helpers.js:74:18)
        at Object.<anonymous> (/Users/silasniewierra/Documents/Coding/test/test-spline/node_modules/@splinetool/react-spline/dist/react-spline.cjs.js:1:546)
        at Module._compile (internal/modules/cjs/loader.js:999:30)
        at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10) {
      page: '/'
    }
    Warning: data for page "/_error" is 430 kB which exceeds the threshold of 128 kB, this amount of data can reduce performance.
    
    Bildschirmfoto 2022-07-01 um 17 02 32

    ! Even if I don't use the <Spline> component and just import it on the top, the error appears.

    opened by SilasNiewierra 6
  • Add

    Add "types" field to package.json "exports"

    In TypeScript 4.7, the nodenext and node16 module resolution options were added to better support native ESM in Node.js. When the package.json "exports" field exists, however, they require a "types" field to exist within each entrypoint, or else types won't be resolved when using one of these module resolution options.

    Currently, using this library with either of those settings throws the following TypeScript error:

    error TS7016: Could not find a declaration file for module '@splinetool/react-spline'. '/project-path/node_modules/@splinetool/react-spline/dist/react-spline.cjs.js' implicitly has an 'any' type.
      Try `npm i --save-dev @types/splinetool__react-spline` if it exists or add a new declaration (.d.ts) file containing `declare module '@splinetool/react-spline';
    

    This PR fixes this issue by adding the "types" field to "exports" for the "./" entrypoint. The same change is required for @splinetool/runtime, but I couldn't find a link to a repository where I could submit the change.

    opened by futurGH 5
  • Uncaught TypeError: L.Application is not a constructor

    Uncaught TypeError: L.Application is not a constructor

    Hi, I'm having some issues rendering my spline onto my project. It all looks fine on the CodeSanbox link provided but when using it within my own app, there seems to be an issue. I am using React w/ Typescript and webpack. Here is the component:

    image

    Whenever I try to render the component, a TypeError is thrown regarding L.Application is not a constructor:

    image

    I'm not really sure what the error means but it was addressing a ForwardRef component so it could potentially be something around the ForwardRefExocticComponent as shown below

    image

    Please let me know if you have any ideas. Thanks 🙂

    opened by mr-akashdesai 5
  • Hydration failed because the initial UI does not match what was rendered on the server

    Hydration failed because the initial UI does not match what was rendered on the server

    Running into a super odd bug with React 18 & Next.js 13

    CleanShot 2022-11-27 at 16 22 44

    I suspect it's related to the infamous Hydration failed because the initial UI does not match what was rendered on the server. error: https://github.com/vercel/next.js/discussions/35773

    However, even when I tried dynamically importing the Spline component with next/dynamic and workarounds like this, the problem still persisted.

    I'm at a complete loss and had to remove the Spline component temporarily to not break my app 😓

    Would love some help debugging this. Here's my code: https://github.com/steven-tey/dub/blob/main/components/app/welcome/intro.tsx#L33-L37

    opened by steven-tey 4
  • CORS: Unhandled Runtime Error

    CORS: Unhandled Runtime Error

    Hey, i'm developing a site locally on localhost:3000 and I'm receiving the following error ion console:

    Access to fetch at 'https://prod.spline.design/PVMoc332wUkkwrCV/scene.splinecode' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
    

    I've taken a look at the docs but can't see anything that suggests i cant put this into my project locally ?

    import Spline from '@splinetool/react-spline';
    
    export default function App() {
      return (
        <Spline scene="https://prod.spline.design/PVMoc332wUkkwrCV/scene.splinecode" />
      );
    }
    
    opened by mattsince87 4
  • React Native is not supported

    React Native is not supported

    I checked the issues, It seems that many people have the same problem as me, but no solution.

    I tried react-spline with react-three-fiber, there are two problems to be solved.

    Problem 1

    react-spline load spline file from url, but React Native not support FileReader.readAsArrayBuffer.

    Related issues

    https://github.com/facebook/react-native/issues/21209

    https://github.com/facebook/react-native/pull/30769

    We can add the polyfill of FileReader.readAsArrayBuffer at SplineLoader. I tried, it work. see: https://github.com/facebook/react-native/issues/21209#issuecomment-495294672

    Problem 2

    I use spline generate the code of react-three-fiber, but it and example code of the react-three-fiber docs are different.

    spline generate code

    <mesh
      name="Rectangle"
      geometry={nodes.Rectangle.geometry}
      material={materials['Rectangle Material']}
      castShadow
      receiveShadow
      position={[3, -13.1, 0]}
      rotation={[-Math.PI / 2, 0, 0]}
      scale={1}
    />
    

    Example code of the react-three-fiber docs

    <mesh
      {...props}
      ref={mesh}
      scale={active ? 1.5 : 1}
      onClick={(event) => setActive(!active)}
      onPointerOver={(event) => setHover(true)}
      onPointerOut={(event) => setHover(false)}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
    

    I'm looking for a way to convert between them. After their conversion, spline can work perfectly in React Native.

    opened by yunying1 2
  • Click events not working reliably with window resize & scrolling

    Click events not working reliably with window resize & scrolling

    Using the latest versions and I'm having issues with click events not firing. Might be related to this issue https://github.com/splinetool/react-spline/issues/86.

    How to repro:

    • Scroll down,
    • Resize window couple of times
    • Attempt to click to toggle state

    Sometimes it works, sometimes it doesn't. Fails 40% of the time. Seems the "hitbox" of the element doesn't sync with the position of the 3D element in the DOM.

    React Sandbox: https://uwg187.csb.app/

    Spline file: https://app.spline.design/file/30c48d7b-52a5-4f82-838e-7762567527ae

    Settings: image

    Versions:

    "@splinetool/react-spline": "^2.2.5",
    "@splinetool/runtime": "^0.9.153",
    

    Gif of bug: https://cdn.discordapp.com/attachments/936730866896502834/1033777594753097808/bug.gif

    opened by sebastiangraz 2
  • Can I know the progress level of an animation ?

    Can I know the progress level of an animation ?

    Hello!

    Is it possible to know the progress of the animation ? I have two types of animation, one on scroll and one on "lookat".

    I want to make sure scrolling animation does not reverse and I want to enable the second animation only once scrolling animation is done.

    opened by RoudyTarabay 1
  • [Bug] Post-Processing breakes rendering on mobile.

    [Bug] Post-Processing breakes rendering on mobile.

    i tried multiple simple scenes, when in visual studio on a browser emulating mobile, it works fine, but when deployed on gh-pages and actually opened on a phone, it just turns into a black screen and it breaks. When post-processing gets turned off and the link updated, it starts working fine again and it renders out the scene normaly. Any other variable doesn't seem to matter, even when post processing is turned on but options within it are off, it still doesn't work.

    opened by Tarik1700 8
Releases(v2.2.2)
Owner
Spline
Spline
A mobile-first React prototyping tool with React-Bootstrap component integration

A mobile-first React prototyping tool with React-Bootstrap component integration

OSLabs Beta 48 Apr 17, 2022
Simple React component for smoothy full-page scolling using CSS animations. React Page Scroller

React Page Scroller Simple React component for smoothy full-page scolling. Demo You can scroll the page using mouse wheel, touch scroll or keyboard ar

null 366 Dec 22, 2022
Pranav Teegavarapu 8 Jan 3, 2022
Source code for my tutorial on how to build customizable table component with React Table and Tailwind CSS.

React Table + Tailwind CSS = ❤️ Source code for my tutorial on how to build customizable table component with React Table and Tailwind CSS. Both parts

Samuel Liedtke 145 Dec 28, 2022
A simple calculator built with ReactJs. The purpose is to use React Class Component without hooks in order to get familiar with legacy code.

Simple Calculator This is a simple calculator built with ReactJs. The purpose is to use React Class Component without hooks in order to get familiar w

Emanuel Okello 7 Aug 8, 2021
kbar is a simple plug-n-play React component to add a fast, portable, and extensible command+k interface to your site.

kbar is a simple plug-n-play React component to add a fast, portable, and extensible command+k interface to your site.

Tim 3.6k Jan 5, 2023
Template component for publishing Ionic React Functional Components to npm

ionic-react-component-template This is a template component for publishing Ionic React Functional Components to npm. Copy this template, change a few

null 2 Nov 7, 2022
A beautiful and accessible guitar component for React. ⚛️ 🎸

React-Guitar · A beautiful and accessible guitar component for React. See https://react-guitar.com for a live demo. Projects using React-Guitar Workla

Alejandro Tardín 587 Dec 5, 2022
Macbook computer keyboard style for react component.

React Mac Keyboard Macbook computer keyboard style for react component. Quick Start import { useState } from "react"; import MacKeyboard from "@uiw/re

uiw 14 Apr 28, 2022
React Claymorphism Component

React Claymorphism Component Claymorphism is a new UI Design concept created by Michał Malewicz Thanks codeAdrian to inspired me by creation clay.css

null 4 Mar 29, 2022
A minimalistic e-commerce web page with all the functionality using react class component

Minimalistic e-commerce web page In this project, I build a minimalistic e-commerce web page. Built With Java Script HTML CSS React GraphQl Technologi

Shoira 15 Oct 30, 2022
Zero-dependency, highly customizable rating component for React

React Rating Zero-dependency, highly customizable rating component for React. First released: July 2nd, 2022 Demo and examples Features Use any SVG: N

Simone 163 Dec 28, 2022
A fully customizable, one-time password (OTP) and phone number with separator input component for the web built with React

A fully customizable, one-time password (OTP) and phone number with separator input component for the web built with React. Tested on Web, Android, and iOS. This package supports all react versions.

Ritik Banger 20 Dec 15, 2022
A react component that adds a watermark to an area of a web page.

react-watermark A react component that adds a watermark to an area of a web page. Example Preview: https://uiwjs.github.io/react-watermark Install Not

uiw 21 Nov 28, 2022
Move react component lifecycle to worker and render to DOM

Move react component lifecycle to worker and render to DOM

yiminghe 41 Oct 22, 2022
.NET on WASM inside a react component

.NET on WASM in a react component This sample shows how to use .NET on WASM integrated into a react application. It goes one step further and extract

Marek Fišera 12 Dec 16, 2022
This is an application, something like todo app in react but more advanced. It includes hooks, conditionals, styled-component, and many more

Expenses project in React. This project is based on Maximilan Schwarzmuller react course on Udemy. It covers all the topcis that react developer shoul

Michał Zalewski 0 Sep 27, 2022
A React component wrapper for Vimeo video player iFrames.

React Vimeo Provider Open docs → Install via npm npm i react-vimeo-provider Import import {VimeoProvider} from "react-vimeo-provider"; Use <VimeoProvi

Kyle 1 Mar 31, 2022
⌨️ A User-friendly, easy-to-use, scalable, and highly customizable component for automating your command+k experience.

ScoutBar ⌨️ Spolight for your app See Demo On Codesandbox See Documentation ⚡️ Overview Users enjoy hitting CMD + K to search and perform complex acti

Adenekan Wonderful 102 Dec 29, 2022