<Gizmo>
A gizmo for snap-to camera controls.
Uses the Three Viewport Gizmo library.
<script lang="ts"> import type { Vector3Tuple } from 'three' import { Canvas, T } from '@threlte/core' import { Gizmo, type GizmoOptions, OrbitControls } from '@threlte/extras' import { Folder, List, Pane, Slider, ThemeUtils } from 'svelte-tweakpane-ui' import Scene from './Scene.svelte'
let type = $state<'sphere' | 'cube' | undefined>('sphere') let speed = $state(1) let placement = $state<GizmoOptions['placement']>('bottom-left') let size = $state(86) let left = $state(10) let top = $state(10) let right = $state(10) let bottom = $state(10) let center = $state<Vector3Tuple>([0, 0, 0])</script>
<Pane theme={ThemeUtils.presets.light} position="fixed" title="Gizmo"> <List label="type" bind:value={type} options={{ sphere: 'sphere', cube: 'cube' }} /> <Slider label="speed" bind:value={speed} min={0.1} max={1} /> <List label="placement" bind:value={placement} options={[ 'top-left', 'top-center', 'top-right', 'center-left', 'center-center', 'center-right', 'bottom-left', 'bottom-center', 'bottom-right' ]} /> <Slider label="size" bind:value={size} min={20} max={350} step={1} />
<Folder title="offset" expanded={false} > <Slider label="top" bind:value={top} min={0} max={50} step={1} /> <Slider label="left" bind:value={left} min={0} max={50} step={1} /> <Slider label="right" bind:value={right} min={0} max={50} step={1} /> <Slider label="bottom" bind:value={bottom} min={0} max={50} step={1} /> </Folder></Pane>
<div> <Canvas> <T.PerspectiveCamera makeDefault position={[20, 20, 20]} fov={36} target={[0, 0, 0]} > <OrbitControls onchange={(event) => { center = event.target.target.toArray() }} > <Gizmo {type} {speed} {placement} {size} offset={{ top, left, bottom, right }} /> </OrbitControls> </T.PerspectiveCamera>
<Scene {center} /> </Canvas></div>
<style> div { position: relative; height: 100%; width: 100%; background-color: rgb(14, 22, 37); }</style><script lang="ts"> import { T } from '@threlte/core' import { Grid } from '@threlte/extras' import { BufferAttribute } from 'three'
type Props = { center: [number, number, number] }
let { center }: Props = $props()
const red = [1, 0, 0] const green = [0, 1, 0] const blue = [0, 0, 1]
const colors = new Float32Array([ ...red, ...red, ...red, ...red, ...red, ...red, ...red, ...red, ...green, ...green, ...green, ...green, ...green, ...green, ...green, ...green, ...blue, ...blue, ...blue, ...blue, ...blue, ...blue, ...blue, ...blue ])</script>
<T.AxesHelper args={[5]} renderOrder={1}/>
<Grid sectionSize={0} cellColor="#eee"/>
<T.Mesh position={center}> <T.BoxGeometry oncreate={(ref) => { ref.setAttribute('color', new BufferAttribute(colors, 3)) }} /> <T.MeshBasicMaterial vertexColors /></T.Mesh>Three’s OrbitControls or yomotsu’s CameraControls can be provided as a controls prop.
Alternatively, the <Gizmo> can be placed as a child of a controls component.
<OrbitControls> <!-- Will attach itself to this OrbitControls --> <Gizmo /></OrbitControls>In addition to the props listed below, <Gizmo> can accept any of the options from the underlying Three Viewport Gizmo instance as a prop.
These props cause the gizmo to rebuild itself, so update them sparingly.