Events (v0.3.2)

You can easily handle mouse or touch events on your meshes.

TIP

To be able to handle events on ThreeJS objects, TroisJS uses raycasting.

Read more : https://threejs.org/docs/#api/en/core/Raycaster

Mesh Events

You can use the following props to handle events on a Mesh or InstancedMesh:

NameDescriptionEvent typeParameters
onPointerEnterWhen the pointer enters a meshpointerenter{ type, over: true, component, intersect }
onPointerOverWhen the pointer enters or leaves a meshpointerover{ type, over, component, intersect? }
onPointerMoveWhen the pointer moves over a meshpointermove{ type, component, intersect }
onPointerLeaveWhen the pointer leaves a meshpointerleave{ type, over: false, component }
onClickWhen the pointer clicks on a meshclick{ type, component, intersect }

Example :

<template>
  <Renderer antialias resize="window">
    <Camera :position="{ z: 10 }" />
    <Scene>
      <PointLight :position="{ y: 10, z: 10 }" />
      <Box
        @pointerEnter="onPointerEvent"
        @pointerOver="onPointerOver"
        @pointerMove="onPointerEvent"
        @pointerLeave="onPointerEvent"
        @click="onPointerEvent"
      >
        <LambertMaterial />
      </Box>
    </Scene>
  </Renderer>
</template>

<script>
export default {
  methods: {
    onPointerEvent(event) {
      console.log(event);
    },
    onPointerOver(event) {
      event.component.mesh.material.color.set(event.over ? 0xff0000 : 0xffffff);
    },
  },
};
</script>

Raycaster Component

If you need to easily handle pointer events on all your scene's meshes, you can use Raycaster component :

<template>
  <Renderer antialias resize="window">
    <Camera :position="{ z: 10 }" />
    <Raycaster
      @pointerEnter="onPointerEvent"
      @pointerOver="onPointerOver"
      @pointerMove="onPointerEvent"
      @pointerLeave="onPointerEvent"
      @click="onPointerEvent"
    />
    <Scene>
      <PointLight :position="{ y: 10, z: 10 }" />
      <Box v-for="i in 5" :position="{ x: -6 + i * 2 }">
        <LambertMaterial />
      </Box>
    </Scene>
  </Renderer>
</template>

<script>
export default {
  methods: {
    onPointerEvent(event) {
      console.log(event);
    },
    onPointerOver(event) {
      event.component.mesh.material.color.set(event.over ? 0xff0000 : 0xffffff);
    },
  },
};
</script>

intersectMode

By default, raycasting will be made on pointer move, but it can be useful to do the same on every frame.

If using mesh events, you should set pointer prop on Renderer :

<Renderer :pointer="{ intersectMode: 'frame' }">
  ...
</Renderer>

If using Raycaster component, you should set intersect-mode prop :

<Raycaster intersect-mode="frame" />

intersectRecursive

If present (=true), it also checks all descendants. Otherwise it only checks intersection with the object.

Default is false.

<Raycaster intersect-recursive />

Starting in v0.3.2 GLTF-models accept raycasting events as well. To make use of this you have to set intersectRecursive to true depending on your implementation:

  1. Mesh based events (each mesh reports needs its own interaction events)
<Renderer :pointer="{ intersectRecursive: true }">
  <Camera :position="{ z: 1 }" />
  <Scene>
    <GltfModel @click="onClick" src="..." />
  </Scene>
</Renderer>
  1. Raycaster based implementation (one event fires no matter which object reports a collision)
<Renderer>
  <Camera :position="{ z: 1 }" />
  <Scene>
    <Raycaster intersect-recursive @click="onClick" />
    <GltfModel src="..." />
  </Scene>
</Renderer>