useProgress
Convenience hook that wraps THREE.DefaultLoadingManager.
<script lang="ts"> import Scene from './Scene.svelte' import { Canvas } from '@threlte/core' import { Tween } from 'svelte/motion' import { fade } from 'svelte/transition' import { fromStore } from 'svelte/store' import { useProgress } from '@threlte/extras'
const { progress } = useProgress() const p = fromStore(progress)
const tweenedProgress = Tween.of(() => p.current, { duration: 150 })
const progressWidth = $derived(100 * tweenedProgress.current) const progressLessThanOne = $derived(tweenedProgress.current < 1)</script>
{#if progressLessThanOne} <div transition:fade={{ duration: 200 }} class="wrapper" > <p class="loading">Loading</p> <div class="bar-wrapper"> <div class="bar" style="width: {progressWidth}%" ></div> </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 type { Material, Mesh } from 'three' import { Environment, useGltf } from '@threlte/extras' import { T, useTask } from '@threlte/core'
let rotation = $state(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 )</script>
<Environment url="/textures/equirectangular/hdr/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}> {#await gltf then { nodes }} <T is={nodes['node_damagedHelmet_-6514']} /> {/await}</T.Group>Model: Battle Damaged Sci-fi Helmet by theblueturtle_
Examples
Section titled “Examples”Basic Example
Section titled “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>