@threlte/extras
transitions
The plugin transitions
enables Svelte-like transitions on Threlte components.
<script lang="ts">
import { Canvas } from '@threlte/core'
import Scene from './Scene.svelte'
let showCube = true
</script>
<div class="relative h-full w-full">
<div
class="pointer-events-none absolute left-0 top-0 flex h-[60%] w-full items-center justify-center"
>
<button
class="border-orange/5 text-orange pointer-events-auto rounded-sm border bg-orange-800/50 px-2 py-1 text-sm hover:bg-orange-800/70 hover:text-orange-400 focus:outline-none"
on:click={() => {
showCube = !showCube
}}
>
{#if showCube}
Hide Cube
{:else}
Show Cube
{/if}
</button>
</div>
<Canvas>
<Scene {showCube} />
</Canvas>
</div>
<script lang="ts">
import { T } from '@threlte/core'
import { createTransition } from '@threlte/extras'
import { cubicOut } from 'svelte/easing'
import type { Material, Mesh } from 'three'
const fade = createTransition<Material>((ref) => {
if (!ref.transparent) ref.transparent = true
return {
tick(t) {
ref.opacity = t
},
easing: cubicOut,
duration: 400
}
})
const scale = createTransition<Mesh>((ref) => {
return {
tick(t) {
// t is [0,1] and needs to be converted to [0.5,1]
t = 0.5 + t * 0.5
ref.scale.set(t, t, t)
},
easing: cubicOut,
duration: 400
}
})
const fly = createTransition<Mesh>((ref) => {
return {
tick(t) {
// t is [0,1] and needs to be converted to [1,0]
t = 1 - t
ref.position.y = t
},
easing: cubicOut,
duration: 400
}
})
</script>
<T.Mesh
in={fly}
out={scale}
>
<T.BoxGeometry />
<T.MeshStandardMaterial
color="#A854F7"
transition={fade}
/>
</T.Mesh>
<script lang="ts">
import { T } from '@threlte/core'
import { transitions } from '@threlte/extras'
import { DEG2RAD } from 'three/src/math/MathUtils.js'
import Cube from './Cube.svelte'
export let showCube = true
transitions()
</script>
<T.PerspectiveCamera
position={[8, 5, 8]}
on:create={({ ref }) => {
ref.lookAt(0, 0, 0)
}}
makeDefault
/>
<T.DirectionalLight position={[3, 15, 10]} />
<T.AmbientLight />
{#if showCube}
<Cube />
{/if}
<T.Mesh
rotation.x={-90 * DEG2RAD}
position.y={-0.5}
>
<T.PlaneGeometry args={[4, 4]} />
<T.MeshStandardMaterial color="#281543" />
</T.Mesh>
The plugin transitions
hooks deep into the <T>
Svelte component and changes to the runtime syntax of Svelte may break this plugin. If you encounter any issues, please open an issue on GitHub. It’s recommended to lock the version of Svelte to a specific version.
Usage
To use Threlte transitions, you need to inject the plugin first via invoking transitions()
. All child <T>
components will then accept transition properties.
createTransition
Threlte Transitions use Svelte transitions under the hood and therefore use a similar API. The function createTransition
is used to conveniently create a transition.
import type { Material } from 'three'
import { createTransition } from '@threlte/extras'
import { cubicOut } from 'svelte/easing'
const fade = createTransition<Material>((ref) => {
ref.transparent = true
return {
tick(t) {
// t is [0,1]
ref.opacity = t
},
easing: cubicOut,
duration: 400,
delay: 100
}
})
The transition fade
can now be applied to all <T>
components that instantiate classes extending THREE.Material
like THREE.MeshBasicMaterial
or THREE.MeshStandardMaterial
:
<T.MeshStandardMaterial transition={fade} />
Transition Directions
Run a transition only when the component mounts:
<T.MeshStandardMaterial in={fade} />
Run a transition only when the component unmounts:
<T.MeshStandardMaterial out={fade} />
Run a transition when the component mounts or unmounts:
<T.MeshStandardMaterial transition={fade} />
To react on different transition directions in the same transition, you can use the direction
parameter:
import { createTransition } from '@threlte/extras'
// direction is 'in', 'out' or 'both'
const fly = createTransition((ref, { direction }) => {
// …
})
Transition Parameters
To make reusing transitions throughout your application easier, make createTransition
the return value of a function that accepts parameters:
import { createTransition } from '@threlte/extras'
const scale = (duration: number) => {
return createTransition((ref) => {
return {
tick(t) {
ref.scale.setScalar(t)
},
duration
}
})
}
The transition can now be used like this:
<T.Mesh transition={scale(400)} />
Transition Events
Similar to Svelte transitions, Threlte transitions also emit events:
{#if visible}
<T.Mesh
{geometry}
{material}
transition={fade}
on:introstart={() => console.log('intro started')}
on:outrostart={() => console.log('outro started')}
on:introend={() => console.log('intro ended')}
on:outroend={() => console.log('outro ended')}
/>
{/if}
Limitations
Transitions are always global
Threlte transitions cannot be declared as local and therefore transitions will run when any upstream component mounts or unmounts.
Threlte transitions always “intro”
As opposed to Svelte transitions, in
and transition
transitions will also run on the first render of a component.