
A three.js component library for svelte.
Featured Content Ads
add advertising here
Index
- What is threlte?
- Getting started
- Concepts
- Interactivity
- Viewport Awareness
- Reactivity
- Conventions
- Reference
- Types
- Property Types
- Context Types
- Components
📋 🌐 Objects🌐 🌐 🌐 🌐
♻️ Object Instances♻️ ♻️ ♻️ ♻️
🔆 Lights🔆 🔆 🔆 🔆 🔆
🎥 Cameras🎥 🎥
🔁 Controls🔁
💄 Post Processing💄
- Misc
💭 💭 🔤 🔲 🔗
↩️ Hooks↩️ useThrelte↩️ useThrelteRoot↩️ useFrame↩️ useLoader↩️ useTexture
- Types
- Credits
- Thank you
- License
What is threlte?
Threlte is a component library for svelte to build and render three.js scenes declaratively and state-driven in Svelte apps.
It’s inspired by the sensible defaults of react-three-fiber, the simplicity and effectiveness of Sveltes reactivity model and Svelte Cubed.
It provides strictly typed components to quickly and easily build three.js scenes with deep reactivity and interactivity out-of-the-box.
Featured Content Ads
add advertising hereIt also aims to provide the building blocks to quickly extend threlte when it’s needed.
⚠️ threlte is still in development and you should expect breaking changes. Check the release notes before updating. If you want to be in the safe side, install threlte withnpm i threlte three --save-exact
to lock the version.
Getting started
Install threlte and three.js:
npm install threlte three
For TypeScript users, install three.js types:
Featured Content Ads
add advertising herenpm install -D @types/three
Build your first scene:
Open in CodeSandbox
It should look something like this:
Congratulations
Orbit around the cube and have fun using threlte.
Check out the slightly advanced example scene including interactivity on CodeSandbox.
Concepts
Yes, there are already three.js component libraries for svelte, threlte is different in some ways:
- Sensible defaults
Much like react-three-fiber, threlte will set sensible defaults to three.jsWebGLRenderer
, all colors and textures and more. This makes it easy for you to follow best practices in terms of color reception and accuracy.
threlte also makes visibility management a breeze with its
component. - Unified frame loop
By default, threlte only renders the scene if there’s need for it: If a prop changes that makes rendering the scene necessary, if there are any interactive objects in the scene or if threlte or you useuseFrame
in any of your components. - Interactivity
threlte makes it possible to use events on three.js objects as if they were regular DOM elements:
You can also listen to your object leaving or entering the viewport:
- TypeScript
All threlte components are written in TypeScript, so type support is a first-class citizen. - EffectComposer support
Add a Pass with
and threlte will take care of setting up the defaultRenderPass
and render to theEffectComposer
instead of theWebGLRenderer
. - Text rendering
Render text using the fantastic troika-three-text library with:
- Access All Areas
- Bind to three.js object instances
- Access the renderer
const { renderer, invalidate } = useThrelte()
- Bind to three.js object instances
- Easily extendable
Build objects that didn’t yet make it to threlte yourself by plugging together functional components. - Tree-shakeble
react-three-fiber is great at making it possible to use three.js classes as JSX components. This means that there is no hard dependency on a certain three.js version and everything that is possible in three.js is covered with react-three-fiber as well. There is however a downside: react-three-fiber looks up three.js classes at runtime. This means that even if your react-three-fiber app only uses a fraction of three.js, you will need to ship three.js in its entirety.
threlte does not look up three.js classes at runtime and as such is limited in features compared to three.js itself. It tries however to cover most use cases of three.js and provides functional components to make extending threlte as easy as possible. As such, your bundler is able to tree-shake threlte and limit what parts of three.js get shipped. - Does not get in your way
Everything is accessible. Objects are instantiated without any default values, so that threlte will not get in your way of setting up or altering objects manually while also relying on the defaults set by three.js.
Interactivity
Open the interactivity example in CodeSandbox
Listen to events of a
and a
as if it would be a regular DOM element:
click
contextmenu
pointerup
pointerdown
pointerenter
pointerleave
pointermove
All events include the raycast Intersection object:
All events but pointerleave
and pointerenter
also include the underlying PointerEvent
or MouseEvent
:
interactive
to your component to be able to listen to pointer events
Be aware that this will make the frameloop render on every frame.
Viewport Awareness
Open the viewport awareness example in CodeSandbox
Additionally, most Objects (Lights, Cameras, Meshes, …) can be made viewport aware. Use it to lazily load textures, models and more.
These events are supported:
viewportenter
viewportleave
Bind inViewport
if you wish to not use events.
⚠️ You must addviewportAware
to your component to make it viewport aware
Reactivity
Open the reactivity example in CodeSandbox
Just like Svelte Cubed and much unlike react-three-fiber it is encouraged to use your component state to drive your three.js scene.
By using props instead of manipulating three.js objects directly, the unified render loop is able to tell that your scene needs rerendering and svelte can make use of component optimizations.
Conventions
Threlte components follow the principles of three.js whereever possible and useful in terms of available properties and events and their respective naming.
Most component properties are undefined
by default. Therefore, new three.js objects are instantiated without any optional default values. This way, three.js will provide the defaults and threltes reactivity will not kick in, allowing you to take complete control over objects.
On top of that, threlte adds some functionality to make objects even more reactive.
lookAt
Use the property lookAt
on an Object to
- reactively orient an Object3D towards another Object3D
Types
TypeScript users should install @types/three in order to get type support for three.js.
npm install -D @types/three
Property Types
To make working with component props easier, threlte includes special types for position, scale, rotation and lookAt:
type Position = THREE.Vector3 | { x?: number, y?: number, z?: number } const positionA = new Vector3() const positionB = { x: 1, z: 1 } type Scale = THREE.Vector3 | number | { x?: number, y?: number, z?: number } const scaleA = new Vector3() const scaleB = 2 const scaleC = { x: 1.5, z: 1 } type Rotation = THREE.Euler | { x?: number, y?: number, z?: number, order?: THREE.Euler['order'] } const rotationA = new Euler() const rotationB = { x: 1.5, z: 1 } type LookAt = THREE.Vector3 | { x?: number, y?: number, z?: number } | THREE.Object3D const lookAtA = new Vector3() const lookAtB = { x: 2, y: 3 } const lookAtC = someMesh
Context Types
The component provides two very useful contexts:
ThrelteContext
and ThrelteRootContext
useThrelte
and useThrelteRoot
on how to use these.
Components
Type information for threlte component properties, bindings and events are detailed below in the following form:
// optional name: type = default // required name: type
📋
The component is the root of your three.js scene.
By default, the element and the renderer will resize to fit the parent element whenever the window resizes. Provide the property
size
to set a fixed size.
also provides a default camera, located at
{ z: 5 }
.
Properties
// optional dpr: number = browser ? window.devicePixelRatio : 1 flat: boolean = false linear: boolean = false frameloop: 'always' | 'demand' = 'demand' debugFrameloop: boolean = false shadows: boolean = true shadowMapType: THREE.ShadowMapType = THREE.PCFSoftShadowMap size: { width: number, height: number } | undefined = undefined rendererParameters: THREE.WebGLRendererParameters | undefined = undefined
Bindings
ctx: ThrelteContext rootCtx: ThrelteRootContext
See Context Types for details
🌐 Objects
🌐
Example
// required geometry: THREE.BufferGeometry material: THREE.Material | THREE.Material[] // optional position: Position | undefined = undefined scale: Scale | undefined = undefined rotation: Rotation | undefined = undefined lookAt: LookAt | undefined = undefined viewportAware: boolean = false castShadow: boolean | undefined = undefined receiveShadow: boolean | undefined = undefined frustumCulled: boolean | undefined = undefined renderOrder: number | undefined = undefined interactive: boolean = false ignorePointerEvents: boolean = false
Bindings
inViewport: boolean mesh: THREE.Mesh
Events
Example
<script> import { Group, GLTF } from 'threlte' script> <Group position={{ x: 5 }}> <GLTF url={"/models/modelA.glb"} /> <GLTF url={"/models/modelB.glb"} /> Group>
Properties
// optional position: Position | undefined = undefined scale: Scale | undefined = undefined rotation: Rotation | undefined = undefined lookAt: LookAt | undefined = undefined viewportAware: boolean = false castShadow: boolean | undefined = undefined receiveShadow: boolean | undefined = undefined frustumCulled: boolean | undefined = undefined renderOrder: number | undefined = undefined
Bindings
inViewport: boolean group: THREE.Group
Events
viewportenter: undefined viewportleave: undefined
🌐
Example
You might want to use this component to pass as a reference to other components:
// optional position: Position | undefined = undefined scale: Scale | undefined = undefined rotation: Rotation | undefined = undefined lookAt: LookAt | undefined = undefined viewportAware: boolean = false castShadow: boolean | undefined = undefined receiveShadow: boolean | undefined = undefined frustumCulled: boolean | undefined = undefined renderOrder: number | undefined = undefined
Bindings
inViewport: boolean object: THREE.Object3D
Events
viewportenter: undefined viewportleave: undefined
🌐
To use DRACO compression, provide a path to the DRACO decoder.
To use KTX2 compressed textures, provide a path to the KTX2 transcoder.
You are able to change the property url
to load new 3D content. New content will be swapped as soon as loading is finished.
Example
// required url: string // optional position: Position | undefined = undefined scale: Scale | undefined = undefined rotation: Rotation | undefined = undefined lookAt: LookAt | undefined = undefined viewportAware: boolean = false castShadow: boolean | undefined = undefined receiveShadow: boolean | undefined = undefined frustumCulled: boolean | undefined = undefined renderOrder: number | undefined = undefined dracoDecoderPath: string | undefined = undefined ktxTranscoderPath: string | undefined = undefined
Bindings
gltf: GLTF scene: THREE.Group
Events
load: GLTF // The content finished loading unload: undefined // New content finished loading and the old content is unloaded and disposed error: string // An error occured while loading and parsing viewportenter: undefined viewportleave: undefined
♻️ Object Instances
While object components like
create a new object for you (in the case of
it’s a THREE.Mesh
), an object instance component takes an existing object instance (THREE.Mesh
, THREE.Object3D
, THREE.Light
or THREE.Camera
) as a property and applies reactivity to it. It’s used internally but can also be used to introduce reactivity to objects that need to be instanced manually, imported models or objects that did not yet make it into threlte.
Object instance components intentionally have no default values on properties even if they can be undefined
. That way, your IDE will tell you what properties need to be implemented to properly set them up.
Example
Example
// required object: THREE.Object3D viewportAware: boolean // optional position: Position | undefined scale: Scale | undefined rotation: Rotation | undefined lookAt: LookAt | undefined castShadow: boolean | undefined receiveShadow: boolean | undefined frustumCulled: boolean | undefined renderOrder: number | undefined
Bindings
Events
viewportenter: undefined viewportleave: undefined
♻️
Example
// required mesh: THREE.Mesh interactive: boolean ignorePointerEvents: boolean viewportAware: boolean // optional position: Position | undefined scale: Scale | undefined rotation: Rotation | undefined lookAt: LookAt | undefined castShadow: boolean | undefined receiveShadow: boolean | undefined frustumCulled: boolean | undefined renderOrder: number | undefined
Bindings
Events
Example
// required camera: THREE.Camera viewportAware: boolean useCamera: boolean // optional position: Position | undefined scale: Scale | undefined rotation: Rotation | undefined lookAt: LookAt | undefined castShadow: boolean | undefined receiveShadow: boolean | undefined frustumCulled: boolean | undefined renderOrder: number | undefined
Bindings
Events
viewportenter: undefined viewportleave: undefined
♻️
Example
// required light: THREE.Light viewportAware: boolean // optional position: Position | undefined scale: Scale | undefined rotation: Rotation | undefined lookAt: LookAt | undefined castShadow: boolean | undefined receiveShadow: boolean | undefined frustumCulled: boolean | undefined renderOrder: number | undefined color: THREE.ColorRepresentation | undefined intensity: number | undefined
Bindings
Events
viewportenter: undefined viewportleave: undefined
🔆 Lights
🔆
Example
// optional position: Position | undefined = undefined scale: Scale | undefined = undefined rotation: Rotation | undefined = undefined lookAt: LookAt | undefined = undefined viewportAware: boolean = false castShadow: boolean | undefined = undefined receiveShadow: boolean | undefined = undefined frustumCulled: boolean | undefined = undefined renderOrder: number | undefined = undefined color: THREE.ColorRepresentation | undefined = undefined intensity: number | undefined = undefined
Bindings
inViewport: boolean light: THREE.AmbientLight
Events
viewportenter: undefined viewportleave: undefined
🔆
Example
// optional position: Position | undefined = undefined scale: Scale | undefined = undefined rotation: Rotation | undefined = undefined lookAt: LookAt | undefined = undefined viewportAware: boolean = false receiveShadow: boolean | undefined = undefined frustumCulled: boolean | undefined = undefined renderOrder: number | undefined = undefined color: THREE.ColorRepresentation | undefined = undefined intensity: number | undefined = undefined shadow: | boolean | { mapSize?: [number, number] | undefined camera?: | { left?: number | undefined right?: number | undefined top?: number | undefined bottom?: number | undefined near?: number | undefined far?: number | undefined } | undefined bias?: number | undefined radius?: number | undefined } | undefined = undefined
Bindings
inViewport: boolean light: THREE.DirectionalLight
Events
viewportenter: undefined viewportleave: undefined
🔆
Example
// optional position: Position | undefined = undefined scale: Scale | undefined = undefined rotation: Rotation | undefined = undefined lookAt: LookAt | undefined = undefined viewportAware: boolean = false receiveShadow: boolean | undefined = undefined castShadow: boolean | undefined = undefined frustumCulled: boolean | undefined = undefined renderOrder: number | undefined = undefined intensity: number | undefined = undefined skyColor: THREE.ColorRepresentation | undefined = undefined groundColor: THREE.ColorRepresentation | undefined = undefined
Bindings
inViewport: boolean light: THREE.HemisphereLight
Events
viewportenter: undefined viewportleave: undefined
🔆
Example
// optional position: Position | undefined = undefined scale: Scale | undefined = undefined rotation: Rotation | undefined = undefined lookAt: LookAt | undefined = undefined viewportAware: boolean = false receiveShadow: boolean | undefined = undefined frustumCulled: boolean | undefined = undefined renderOrder: number | undefined = undefined color: THREE.ColorRepresentation | undefined = undefined intensity: number | undefined = undefined distance: number | undefined = undefined decay: number | undefined = undefined power: number | undefined = undefined shadow: | boolean | { mapSize?: [number, number] camera?: { near?: number; far?: number } bias?: number radius?: number } | undefined = undefined
Bindings
inViewport: boolean light: THREE.PointLight
Events
viewportenter: undefined viewportleave: undefined
🔆
Example
// optional position: Position | undefined = undefined scale: Scale | undefined = undefined rotation: Rotation | undefined = undefined lookAt: LookAt | undefined = undefined viewportAware: boolean = false receiveShadow: boolean | undefined = undefined frustumCulled: boolean | undefined = undefined renderOrder: number | undefined = undefined color: THREE.ColorRepresentation | undefined = undefined intensity: number | undefined = undefined angle: number | undefined = undefined decay: number | undefined = undefined distance: number | undefined = undefined penumbra: number | undefined = undefined power: number | undefined = undefined target: LookAt | undefined = undefined shadow: | boolean | { mapSize?: [number, number] camera?: { near?: number; far?: number } bias?: number radius?: number } | undefined = undefined
Bindings
inViewport: boolean light: THREE.SpotLight
Events
viewportenter: undefined viewportleave: undefined
🎥 Cameras
🎥
Example
// optional position: Position | undefined = undefined scale: Scale | undefined = undefined rotation: Rotation | undefined = undefined lookAt: LookAt | undefined = undefined viewportAware: boolean = false castShadow: boolean | undefined = undefined receiveShadow: boolean | undefined = undefined frustumCulled: boolean | undefined = undefined renderOrder: number | undefined = undefined useCamera: boolean = true near: number = undefined far: number = undefined zoom: number = undefined
Bindings
inViewport: boolean camera: THREE.OrthographicCamera
Events
viewportenter: undefined viewportleave: undefined
🎥
Example
// optional position: Position | undefined = undefined scale: Scale | undefined = undefined rotation: Rotation | undefined = undefined lookAt: LookAt | undefined = undefined viewportAware: boolean = false castShadow: boolean | undefined = undefined receiveShadow: boolean | undefined = undefined frustumCulled: boolean | undefined = undefined renderOrder: number | undefined = undefined useCamera: boolean = true near: number = undefined far: number = undefined fov: number = undefined
Bindings
inViewport: boolean camera: THREE.PerspectiveCamera
Events
viewportenter: undefined viewportleave: undefined
🔁 Controls
🔁
The component
must be a direct child of a camera component and will mount itself to that camera.
If the properties autoRotate
or enableDamping
are set to true, the frame loop will run continously.
Example
// optional autoRotate: boolean | undefined = undefined autoRotateSpeed: number | undefined = undefined dampingFactor: number | undefined = undefined enableDamping: boolean | undefined = undefined enabled: boolean | undefined = undefined enablePan: boolean | undefined = undefined enableRotate: boolean | undefined = undefined enableZoom: boolean | undefined = undefined keyPanSpeed: number | undefined = undefined keys: | { LEFT: string UP: string RIGHT: string BOTTOM: string } | undefined = undefined maxAzimuthAngle: number | undefined = undefined maxDistance: number | undefined = undefined maxPolarAngle: number | undefined = undefined maxZoom: number | undefined = undefined minAzimuthAngle: number | undefined = undefined minDistance: number | undefined = undefined minPolarAngle: number | undefined = undefined minZoom: number | undefined = undefined mouseButtons: | { LEFT: MOUSE MIDDLE: MOUSE RIGHT: MOUSE } | undefined = undefined panSpeed: number | undefined = undefined rotateSpeed: number | undefined = undefined screenSpacePanning: boolean | undefined = undefined touches: | { ONE: TOUCH TWO: TOUCH } | undefined = undefined zoomSpeed: number | undefined = undefined target: Position | undefined = undefined
Bindings
controls:
NOW WITH OVER +8500 USERS. people can Join Knowasiak for free. Sign up on Knowasiak.com
Read More