<Resize>
Scales up or down a group of objects by the maximum dimension of their bounding box. Object proportions are preserved. This is particularly useful if you want to “normalize” the dimensions of an object to be in the range 0 to 1.
<script lang="ts"> import { Checkbox, Pane } from 'svelte-tweakpane-ui' import Scene from './Scene.svelte' import { Canvas } from '@threlte/core' import { NoToneMapping } from 'three'
let showCylinder = $state(true) let auto = $state(true)</script>
<Pane title="Resize" position="fixed"> <Checkbox label="Show Cylinder" bind:value={showCylinder} /> <Checkbox label="Auto" bind:value={auto} /></Pane>
<div> <Canvas toneMapping={NoToneMapping}> <Scene {showCylinder} {auto} /> </Canvas></div>
<style> div { height: 100%; }</style><script lang="ts"> import { T, useStage, useThrelte } from '@threlte/core' import { Align, Edges, Grid, MeshDiscardMaterial, OrbitControls, Resize } from '@threlte/extras'
let { showCylinder, auto }: { showCylinder: boolean auto: boolean } = $props()
// Create the stages for resizing and aligning const { renderStage, mainStage } = useThrelte() // Resizing must happen *before* aligning, so we need to create a new stage to orchestrate this const resizeStage = useStage(Symbol('resize'), { after: mainStage, before: renderStage }) // Aligning must happen *after* resizing, to take the new size into account const alignStage = useStage(Symbol('align'), { after: resizeStage, before: renderStage })</script>
<T.PerspectiveCamera makeDefault position={5}> <OrbitControls /></T.PerspectiveCamera>
<T.DirectionalLight position={[5, 10, 4]} intensity={Math.PI}/><T.AmbientLight intensity={0.2} />
<Grid cellColor="#1F3153" cellSize={0.5} sectionColor="#1F3153" sectionThickness={3}/>
<T.Mesh position.y={0.5}> <MeshDiscardMaterial /> <T.BoxGeometry /> <Edges color="white" /></T.Mesh>
<Align stage={alignStage} y={1} auto> <Resize stage={resizeStage} {auto} > <T.Mesh> <T.MeshStandardMaterial color="hotpink" /> <T.BoxGeometry /> </T.Mesh> <T.Mesh position.y={1.5}> <T.MeshStandardMaterial color="cyan" /> <T.SphereGeometry /> </T.Mesh> {#if showCylinder} <T.Mesh position.y={3}> <T.MeshStandardMaterial color="yellow" /> <T.CylinderGeometry args={[1, 1.5, 1]} /> </T.Mesh> {/if} </Resize></Align>Choosing the Axis
Section titled “Choosing the Axis”You can choose the axis by providing the axis prop, otherwise the maximum axis
is used.
<Resize axis="x"> <T.Mesh /></Resize>If you use the axis prop, the dimensions will not be normalized to the range 0 to 1 unless the
maximum axis is chosen.
Bring Your Own Box
Section titled “Bring Your Own Box”Use the box prop to provide your own Box3 instance. Doing so allows you to
capture the bounding box of the objects prior to any scaling
<script> import { Box3 } from 'three' const box = new Box3()</script>
<Resize {box}> <T.Mesh /></Resize>
<T.Box3Helper args={[box]} />Normalizing Multiple Objects
Section titled “Normalizing Multiple Objects”If you have a bunch of source objects that are all different sizes, a useful
technique is to wrap each one in a <Resize>. Once they’ve all been normalized,
it may be easier to reason about their relative sizes.
<script lang="ts"> import Scene from './Scene.svelte' import { Canvas } from '@threlte/core' import { Checkbox, Pane } from 'svelte-tweakpane-ui'
let resize = $state(true)</script>
<Pane position="fixed" title="objects"> <Checkbox bind:value={resize} label="resize" /></Pane>
<div> <Canvas> <Scene {resize} /> </Canvas></div>
<style> div { height: 100%; }</style><script lang="ts"> import { OrbitControls, Resize, useGltf } from '@threlte/extras' import { T } from '@threlte/core'
type SceneProps = { resize?: boolean }
let { resize = true }: SceneProps = $props()
const names = ['Duck', 'Flower', 'Fox']
const promises = Promise.all(names.map((name) => useGltf(`/models/${name}.glb`)))
const increment = (2 * Math.PI) / names.length</script>
<T.PerspectiveCamera makeDefault position={[5, 5, 5]}> <OrbitControls /></T.PerspectiveCamera>
<T.AmbientLight intensity={0.2} /><T.DirectionalLight position={[1, 5, 3]} />
{#await promises then objects} {#each objects as { scene }, i} {@const r = increment * i} <T.Group position.x={Math.cos(r)} position.z={Math.sin(r)} > {#if resize} <Resize> <T is={scene} /> </Resize> {:else} <T is={scene} /> {/if} </T.Group> {/each}{/await}In the example above, the fox model is much larger than the duck and flower models. It is so much larger that you may have to pull the camera back in order to see it. Using <Resize> scales each model so that each one fits inside a unit cube. From there, their relative sizes and positions may be easier to work with.
Manual Resizing
Section titled “Manual Resizing”Using the Export
Section titled “Using the Export”You can manually trigger a resize by calling the resize export.
<script> import { Resize } from '@threlte/extras'
let ref = $state<Resize>()
// ... later on ref?.resize()</script>
<Resize bind:this={ref}> <!-- ... --></Resize>Using the Snippet Argument
Section titled “Using the Snippet Argument”You can also use the snippet argument to trigger a resize.
<script> import { Resize } from '@threlte/extras'</script>
<Resize> {#snippet children({ resize })} <T.Mesh oncreate={resize} /> {/snippet}</Resize>