@threlte/extras
useProgress
Convenience hook that wraps THREE.DefaultLoadingManager
.
<script lang="ts">
import { Canvas } from '@threlte/core'
import { useProgress } from '@threlte/extras'
import { tweened } from 'svelte/motion'
import { fade } from 'svelte/transition'
import Scene from './Scene.svelte'
const { progress } = useProgress()
const tweenedProgress = tweened($progress, {
duration: 800
})
$: tweenedProgress.set($progress)
</script>
{#if $tweenedProgress < 1}
<div
transition:fade|local={{
duration: 200
}}
class="wrapper"
>
<p class="loading">Loading</p>
<div class="bar-wrapper">
<div
class="bar"
style="width: {$tweenedProgress * 100}%"
/>
</div>
</div>
{/if}
<div class="main">
<Canvas>
<Scene />
</Canvas>
</div>
<style>
div.main {
height: 100%;
}
.wrapper {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: white;
display: flex;
flex-direction: column;
gap: 0.25rem;
align-items: center;
justify-content: center;
color: black;
}
.loading {
font-size: 0.875rem;
line-height: 1.25rem;
}
.bar-wrapper {
width: 33.333333%;
height: 10px;
border: 1px solid black;
position: relative;
}
.bar {
height: 100%;
background-color: black;
}
</style>
<script lang="ts">
import { T, useTask } from '@threlte/core'
import { Environment, useGltf } from '@threlte/extras'
import { derived } from 'svelte/store'
import type { Material, Mesh } from 'three'
let rotation = 0
useTask((delta) => {
const f = 1 / 60 / delta // ~1 at 60fps
rotation += 0.01 * f
})
type GLTFResult = {
nodes: {
'node_damagedHelmet_-6514': Mesh
}
materials: {
Material_MR: Material
}
}
const gltf = useGltf<GLTFResult>(
'/models/helmet/DamagedHelmet.gltf?v=' + Math.random().toString() // force a reload on every pageload
)
const helmet = derived(gltf, (gltf) => {
if (!gltf || !gltf.nodes['node_damagedHelmet_-6514']) return
return gltf.nodes['node_damagedHelmet_-6514']
})
</script>
<Environment
path="/hdr/"
files="shanghai_riverside_1k.hdr"
/>
<T.PerspectiveCamera
makeDefault
position.z={10}
fov={20}
/>
<T.DirectionalLight
position.y={10}
position.z={10}
/>
<T.Group rotation.y={rotation}>
{#if $helmet}
<T is={$helmet} />
{/if}
</T.Group>
Model: Battle Damaged Sci-fi Helmet by theblueturtle_
Examples
Basic Example
You can use and place this hook anywhere. Typically you would use this hook outside of your <Canvas>
component to show a loading indicator in your DOM.
<script lang="ts">
// `useProgress` returns readable stores
const {
active, // Readable<boolean> – if the DefaultLoadingManager is active
item, // Readable<string | undefined> – the currently loading item
loaded, // Readable<number> - amount of items loaded
total, // Readable<number> - total amount of items to load
errors, // Readable<string[]> - all error messages
progress, // Readable<number> - normalized (0-1) loading progress
finishedOnce // Readable<boolean> – whether a progress of 1 has been achieved ever.
} = useProgress()
</script>