@threlte/extras
useCursor
A hook that sets the css cursor property according to the hover state of a mesh, so that you can give the user visual feedback.
If a context is present, the cursor property will be set on the DOM element of the renderer, otherwise it will be set on the body element.
<script lang="ts">
import { Canvas } from '@threlte/core'
import Scene from './Scene.svelte'
</script>
<div>
<Canvas>
<Scene />
</Canvas>
</div>
<style>
div {
height: 100%;
}
</style>
<script lang="ts">
import { T, useThrelte } from '@threlte/core'
import { interactivity, Text, useCursor } from '@threlte/extras'
import { DEG2RAD } from 'three/src/math/MathUtils.js'
const { hovering, onPointerEnter, onPointerLeave } = useCursor()
$: color = $hovering ? '#dddddd' : '#FE3D00'
const { size } = useThrelte()
let zoom = $size.width / 7
$: zoom = $size.width / 7
interactivity()
</script>
<T.OrthographicCamera
{zoom}
position={[5, 5, 5]}
oncreate={({ ref }) => {
ref.lookAt(0, 0, 0)
}}
makeDefault
/>
<T.DirectionalLight
position.y={10}
position.x={5}
/>
<T.AmbientLight intensity={0.2} />
<Text
text="HOVER"
interactive
onpointerenter={onPointerEnter}
onpointerleave={onPointerLeave}
fontSize={0.5}
anchorY="100%"
anchorX="50%"
rotation.y={90 * DEG2RAD}
position.y={1}
position.x={-1}
{color}
/>
<T.Mesh
onpointerenter={onPointerEnter}
onpointerleave={onPointerLeave}
>
<T.MeshStandardMaterial {color} />
<T.BoxGeometry args={[2, 2, 2]} />
</T.Mesh>
Examples
Simple Usage
Provide arguments to determine the cursor style. The defaults are'pointer'
for onPointerOver
and 'auto'
for onPointerOut
. useCursor
returns event handlers that you can use to set the hovering state:
<script lang="ts">
import { T } from '@threlte/core'
import { useCursor } from '@threlte/extras'
import { BoxBufferGeometry, MeshBasicMaterial } from 'three'
// Set the cursor to 'grab' if the pointer is
// hovering over the mesh and to 'crosshair'
// if the pointer is outside the mesh
const { onPointerEnter, onPointerLeave } = useCursor('grab', 'crosshair')
</script>
<T.Mesh
onpointerenter={onPointerEnter}
geometry={new BoxBufferGeometry(1, 1, 1)}
material={new MeshBasicMaterial()}
/>
Renaming Event Handlers
You can rename the event handlers to resolve naming conflicts. Additionally Svelte allows binding multiple event handlers to the same event:
<script lang="ts">
import { T } from '@threlte/core'
import { useCursor } from '@threlte/extras'
import { BoxBufferGeometry, MeshBasicMaterial } from 'three'
const { onPointerEnter: cursorEnter, onPointerLeave: cursorLeave } = useCursor()
const onPointerEnter = () => {
console.log('Pointer entered!')
}
const onPointerLeave = () => {
console.log('Pointer left!')
}
</script>
<T.Mesh
onpointerenter={cursorEnter}
onpointerenter={onPointerEnter}
geometry={new BoxBufferGeometry(1, 1, 1)}
material={new MeshBasicMaterial()}
/>
Store Usage
If you want to implement custom logic, you can use the returned svelte store to set the hovering state:
<script lang="ts">
import { T } from '@threlte/core'
import { useCursor } from '@threlte/extras'
import { BoxBufferGeometry, MeshBasicMaterial } from 'three'
const { hovering } = useCursor()
</script>
<T.Mesh
onpointerenter={() => ($hovering = true)}
onpointerleave={() => ($hovering = false)}
geometry={new BoxBufferGeometry(1, 1, 1)}
material={new MeshBasicMaterial()}
/>
Change the Cursor Style
Provide svelte stores to change the cursor style also while hovering:
<script lang="ts">
import { T } from '@threlte/core'
import { useCursor } from '@threlte/extras'
import { BoxBufferGeometry, MeshBasicMaterial } from 'three'
import { writable } from 'svelte/store'
const onPointerOverCursor = writable('grab')
const { onPointerEnter, onPointerLeave } = useCursor(onPointerOverCursor)
// somewhere in your application …
onPointerOverCursor.set('grabbing')
</script>
<T.Mesh
onpointerenter={onPointerEnter}
geometry={new BoxBufferGeometry(1, 1, 1)}
material={new MeshBasicMaterial()}
/>