@threlte/extras
<Gizmo>
A gizmo for snap-to camera controls.
Uses the Three Viewport Gizmo library.
<script lang="ts">
import { Canvas, T, currentWritable, type CurrentWritable } from '@threlte/core'
import { Gizmo, type GizmoOptions, OrbitControls } from '@threlte/extras'
import {
Checkbox,
Color,
Folder,
List,
Pane,
Ring,
Slider,
ThemeUtils
} from 'svelte-tweakpane-ui'
import { OrbitControls as ThreeOrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import Scene from './Scene.svelte'
let type = $state('sphere')
let speed = $state(1)
let placement: GizmoOptions['placement'] = $state('bottom-left')
let size = $state(86)
let left = $state(10)
let top = $state(10)
let right = $state(10)
let bottom = $state(10)
let center: [number, number, number] = $state([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 style="position:relative; height:100%; width:100%; background-color: rgb(14,22,37)">
<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>
<script lang="ts">
import { T } from '@threlte/core'
import { Grid } from '@threlte/extras'
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>
<T.BufferAttribute
args={[colors, 3]}
attach={({ parent, ref }) => {
parent.setAttribute('color', ref)
}}
/>
</T.BoxGeometry>
<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.