@threlte/extras
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 = 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
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>