Skip to content

Basic Animations

This guide will help you get started with basic animations in TresJS.

We will build a simple scene with a cube. We will then animate the cube to rotate around the Y and Z axis.

useLoop

The useLoop composable is the core of TresJS updates, which includes: animations. It allows you to register a callback that will be called every time the renderer updates the scene with the browser's refresh rate.

To see a detailed explanation of how it works, please refer to the useRenderLoop documentation.

ts
const { onBeforeRender } = useLoop()

onBeforeRender(({ delta, elapsed }) => {
  // I will run at every frame ~ 60FPS (depending of your monitor)
})

Getting the reference to the cube

To animate the cube, we need to get a reference to it. We can do it by passing a Template Ref using ref prop to the TresMesh component. This will return the plain THREE instance.

vue
<script setup>
import { shallowRef } from 'vue'

const boxRef = shallowRef()
</script>

<template>
  <TresMesh ref="boxRef">
    <TresBoxGeometry />
    <TresMeshBasicMaterial color="teal" />
  </TresMesh>
</template>
vue
<script setup>
import { TresCanvas } from '@tresjs/core'
import Scene from './Scene.vue'
</script>

<template>
  <TresCanvas>
    <Scene />
  </TresCanvas>
</template>

Animating the cube

Now that we have a reference to the cube, we can animate it. We will use the onBeforeRender method to update the cube's rotation.

ts
const { onBeforeRender } = useLoop()

onBeforeRender(({ delta, elapsed }) => {
  if (boxRef.value) {
    boxRef.value.rotation.y += delta
    boxRef.value.rotation.z = elapsed * 0.2
  }
})

You can also use the delta from the internal THREE clock or the elapsed to animate the cube.

But why not using reactivity?

You might be wondering why we are not using reactivity to animate the cube. The answer is simple, performance.

ts
// This is a bad idea ❌
const boxRotation = ref([0, 0, 0])

onBeforeRender(({ delta, elapsed }) => {
  boxRotation.value[1] += delta
  boxRotation.value[2] = elapsed * 0.2
})

We can be tempted to use reactivity to animate the cube. But it would be a bad idea. The reason is that Vue's reactivity is based on Proxies and it's not designed to be used in a render loop that updates 60 or more times per second.

The embedded page below shows the benchmark of a proxy vs a regular object. As you can see, the proxy is 5 times slower than the regular object.

You can read more about this in the Caveats section.