@threlte/extras
<Float>
This component is a port of drei’s <Float>
component and makes its contents float or hover.
<script lang="ts">
import { Canvas } from '@threlte/core'
import Scene from './Scene.svelte'
</script>
<div>
<Canvas>
<Scene />
</Canvas>
</div>
<style>
div {
height: 100%;
}
</style>
<script lang="ts">
import { T } from '@threlte/core'
import { Float } from '@threlte/extras'
import { onDestroy } from 'svelte'
import { spring } from 'svelte/motion'
import { Color, MeshPhysicalMaterial, type BufferGeometry } from 'three'
export let geometry: BufferGeometry
const red = new Color(0xfe3d00)
const blue = new Color(0x0000ff)
let material = new MeshPhysicalMaterial({
color: red,
reflectivity: 1,
metalness: 0.9,
roughness: 0.2
})
onDestroy(() => {
material.dispose()
})
const scale = spring(1)
const onPointerEnter = () => {
material.color = blue
scale.set(1.1)
}
const onPointerLeave = () => {
material.color = red
scale.set(1)
}
</script>
<Float
floatIntensity={5}
scale={$scale}
rotationIntensity={2}
rotationSpeed={[1, 0.5, 0.2]}
>
<T.Mesh
{geometry}
{material}
onpointerenter={onPointerEnter}
onpointerleave={onPointerLeave}
/>
</Float>
<script lang="ts">
import { T } from '@threlte/core'
import { Environment, Float, Grid, interactivity, useGltf } from '@threlte/extras'
import type { Mesh } from 'three'
import Blob from './Blob.svelte'
type Nodes = 'ball-1' | 'ball-2' | 'ball-3' | 'ball-4' | 'ball-5'
const gltf = useGltf<{
nodes: Record<Nodes, Mesh>
materials: {}
}>('/models/blobs/blobs.glb', {
useDraco: true
})
interactivity()
</script>
<Environment
path="/hdr/"
files="shanghai_riverside_1k.hdr"
/>
<Float
rotationIntensity={0.15}
rotationSpeed={2}
>
<T.PerspectiveCamera
makeDefault
position.y={10}
position.z={10}
fov={90}
oncreate={({ ref }) => {
ref.lookAt(0, 0, 0)
}}
/>
</Float>
<T.DirectionalLight
position.y={10}
position.z={10}
/>
<T.AmbientLight intensity={0.3} />
<Grid
position.y={-10}
sectionThickness={1}
infiniteGrid
cellColor="#dddddd"
sectionColor="#ffffff"
sectionSize={10}
cellSize={2}
/>
{#if $gltf}
{#each Object.values($gltf.nodes) as node}
{#if node.geometry}
<Blob geometry={node.geometry} />
{/if}
{/each}
{/if}
Examples
Basic Example
<script lang="ts">
import { T } from '@threlte/core'
import { Float } from '@threlte/extras'
</script>
<Float
floatIntensity={5}
scale={$scale}
rotationIntensity={2}
>
<T.Mesh>
<T.MeshStandardMaterial color={'orange'} />
<T.BoxGeometry args={[5, 5, 5]} />
</T.Mesh>
</Float>
Floating
floatingRange
determines the allowed range of position trasformation, and by extension the direction in which the children will move. If you provide a single number tuple, like [-0.1,0.1]
the movement will happen on y axis. Alternatively you can provide an array of three tuples to change the movement axes. For example [[0,0],[0,0],[-0.5,0.5]]
will move children between -0.5 and 0.5 relative to the starting position on the Z axis.
Rotation
Rotation is set by rotationSpeed
and rotationIntensity
. Both of them need to be different from 0 to enable rotation. Providing a number
in either of them applies it to all three axes. You get more granual control by passing an array [x: number, y: number, z: number]
. rotationSpeed
is responsible for the speed of the animation and rotationIntensity
for the angle.
seed
is responsible for the starting state of the animations and is random by default. Setting to a fixed value to get a predictable starting result.