Skip to content

Events and Interaction

Fresh

This tutorial will assume some React knowledge.

After we have our continuous loop running the next step would be to allow our mesh to react to user interaction. Let's attach a click handler to the cube and make it bigger on click.

User Interaction

Any Object3D that has a raycast method can receive a large number of events:

jsx
<mesh
  onClick={(e) => console.log('click')}
  onContextMenu={(e) => console.log('context menu')}
  onDoubleClick={(e) => console.log('double click')}
  onWheel={(e) => console.log('wheel spins')}
  onPointerUp={(e) => console.log('up')}
  onPointerDown={(e) => console.log('down')}
  onPointerOver={(e) => console.log('over')}
  onPointerOut={(e) => console.log('out')}
  onPointerEnter={(e) => console.log('enter')}
  onPointerLeave={(e) => console.log('leave')}
  onPointerMove={(e) => console.log('move')}
  onPointerMissed={() => console.log('missed')}
  onUpdate={(self) => console.log('props have been updated')}
/>

Let's add a click handler:

jsx
<mesh onClick={() => alert('Hellooo')}>
  <boxGeometry />
  <meshPhongMaterial color="royalblue" />
</mesh>

Making the Mesh React to Clicks

Let's add state to track if the mesh is active and change its scale:

jsx
const [active, setActive] = useState(false)

Use a ternary operator to set the scale:

jsx
<mesh scale={active ? 1.5 : 1} onClick={() => setActive(!active)}>
  <boxGeometry />
  <meshPhongMaterial color="royalblue" />
</mesh>

Clicking on your mesh will now scale it up and down!

What We Covered

  • Attached a click handler to our mesh using the familiar onClick prop
  • Added some state to track if the mesh is currently active
  • Changed the scale based on that state

Exercises

  • Change other props of the mesh like position or the color of the material on click
  • Use onPointerOver and onPointerOut to change the props of the mesh on hover events

Example with hover:

jsx
function InteractiveMesh() {
  const [active, setActive] = useState(false)
  const [hovered, setHovered] = useState(false)

  return (
    <mesh
      scale={active ? 1.5 : 1}
      onClick={() => setActive(!active)}
      onPointerOver={() => setHovered(true)}
      onPointerOut={() => setHovered(false)}
    >
      <boxGeometry />
      <meshPhongMaterial color={hovered ? 'hotpink' : 'royalblue'} />
    </mesh>
  )
}

Next Steps

We just made our mesh react to user interaction but it looks pretty bland without any transition. In the next chapter let's look at integrating react-spring to turn this into an actual animation.

For more event details, see the full Events API reference page.