@threlte/core
Three
This component is part of a recently released feature of threlte. It is still very much in a beta phase and can be subject to breaking API changes. Please use at your own risk. Learn more about this feature here
The component <Three />
provides the means to use any three.js export as a Svelte component. It does this by leveraging the rigid three.js naming and object property structure and act as a renderer to include objects in the scene graph or attach objects to parent object properties.
Usage
In contrast to other threlte components, the component <Three />
does not wrap a single three.js class or acts in a single domain but rather tries to render any value that is passed to the property type
in the context of a threlte application.
Usage with preprocessor
There are two ways to use the component: With or without the preprocessor.
type
- If a class definition such as
THREE.Mesh
is provided to the propertytype
, it creates an instance of that class.
<!-- equivalent to "new Mesh()" -->
<Three type={Mesh} />
- If a class instance or any other value such as
new THREE.Mesh()
is provided, the component uses this value as-is.
<script>
const mesh = new Mesh()
</script>
<Three type={mesh} />
Depending on certain value types, threlte makes these assumptions:
- If the value passed to
type
is extendingTHREE.Object3D
it's added to the scene graph. - If the value passed to
type
is a disposable, it's disposedonDestroy
. - If the value passed to
type
is extendingTHREE.EventDispatcher
, you can add event callbacks. - If the value passed to
type
is extendingTHREE.Camera
, certain camera-related properties are available.
args
In three.js objects are classes that are instantiated. These classes can receive one-time constructor arguments (new THREE.SphereGeometry(1, 32)
). In Threlte, constructor arguments are always passed as an array via the property args
. If args
change later on, the object must naturally get reconstructed from scratch!
- If a class definition such as
THREE.BoxGeometry
is provided to the propertytype
, the propertyargs
is used to instantiate the class:<Three type={BoxGeometry} args={[1, 2, 1]}>
equalsnew BoxGeometry(1, 2, 1)
.
attach
Use attach
to bind objects to their parent. If you unmount the attached object it will be taken off its parent automatically.
The following attaches a material to the material property of a mesh and a geometry to the geometry property:
<Three type={Mesh}>
<Three type={MeshBasicMaterial} attach="material" />
<Three type={BoxGeometry} attach="geometry" />
</Three>
All native elements ending with "Material" (such as MeshStandardMaterial
) receive attach="material"
, and all elements ending with "Geometry" receive attach="geometry"
automatically. You do not strictly have to type it out!
- The value inferred from the property
type
is "attached" to a parent property.
<script>
import { MeshStandardMaterial } from 'three'
export let texture
</script>
<Three type={MeshStandardMaterial}>
<!-- Attaches the texture to the property "map" of the parent material -->
<Three type={texture} attach="map" />
</Three>
attach
can be a dot-notated path to a nested parent property:
<Three type={DirectionalLight}>
<!--
Attaches an instance of a THREE.OrthographicCamera
to the property camera of the property shadow of the
parent THREE.DirectionalLight
-->
<Three
type={OrthographicCamera}
args={[-1, 1, 1, -1, 0.1, 100]}
attach="shadow.camera"
/>
</Three>
attach
can also be a function which is called on mounting with the parent and the value inferred from the propertytype
. It can return a cleanup function which is calledonDestroy
:
<Three type={DirectionalLight}>
<!--
Attaches an instance of a THREE.OrthographicCamera
to the property camera of the property shadow of the
parent THREE.DirectionalLight
-->
<Three
type={OrthographicCamera}
args={[-1, 1, 1, -1, 0.1, 100]}
attach={(parent, self) => {
parent.shadow.camera = self
return () => {
parent.shadow.camera = null
}
}}
/>
</Three>
Camera Props
By default Threlte is responsive and will set up cameras properly on resize (aspect ratio etc).
Cameras can be controlled manually by setting manual
to true
in camera. This will opt out of projection matrix recalculation when the drawing area resizes or other camera-related properties change.
<Three type={PerspectiveCamera} manual />
Use the property makeDefault
to set a camera to the default rendering camera.
<Three type={PerspectiveCamera} makeDefault />
Events
Adding an event listener to a component will also add the corresponding event listener to the three.js class instance. The event will be forwarded and is available at event.detail
.
This will listen to the "change" event on the THREE.OrbitControls
:
<Three type={OrbitControls} on:change={(e) => {
console.log('OrbitControls changed.', e.detail)
}} />
Slot Props
The value infered from the property type
is available as the slot prop ref
:
<Three type={PerspectiveCamera} let:ref={camera}>
<!--
The slot prop "ref" is used to reference the
camera and instantiate the OrbitControls
-->
<Three type={OrbitControls} args={[camera, renderer.domElement]} />
</Three>
Bindings
The value infered from the property type
is available as the binding ref
:
<script>
let camera
$: console.log(camera)
</script>
<Three type={PerspectiveCamera} bind:ref={camera} />