2.basic-animations.md 3.3 KB


title: Basic Animations description: Learn how to create basic animations in TresJS

thumbnail: /recipes/model-n-animations/basic.png

::examples-basic-animation ::

This recipe covers the fundamentals of creating smooth animations in TresJS.

::steps

Import useLoop composable

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.

import { useLoop } from '@tresjs/core'

const { onBeforeRender } = useLoop()

onBeforeRender(() => {
  // Animation logic here
})

::read-more{to="/api/composables/use-loop"} ::

Get a reference to the object you want to animate

Similar to Vue, you can use template refs to access the Three.js object instance and manipulate its properties. If you want to optimize even further, you can use shallowRef to avoid unnecessary reactivity.

<script setup lang="ts">
import { ref } from 'vue'
import { useLoop } from '@tresjs/core'

const cubeRef = ref<THREE.Mesh | null>(null)
// or use shallowRef if you want to avoid reactivity
// const cubeRef = shallowRef<THREE.Mesh | null>(null)

const { onBeforeRender } = useLoop()

onBeforeRender(() => {
  if (cubeRef.value) {
    cubeRef.value.rotation.x += 0.01
    cubeRef.value.rotation.y += 0.01
  }
})
</script>

<template>
  <TresMesh ref="cubeRef" :position="[0, 1, 0]">
    <TresBoxGeometry :args="[1, 1, 1]" />
    <TresMeshNormalMaterial />
  </TresMesh>
</template>

::read-more{to="/api/advanced/performance#reactivity-and-performance"} To read more about reactivity and performance in TresJS. ::

Use delta

The onBeforeRender callback provides a delta parameter, which represents the time elapsed since the last frame. This is useful for creating frame rate independent animations.

onBeforeRender(({ delta }) => {
  if (cubeRef.value) {
    cubeRef.value.rotation.x += delta
    cubeRef.value.rotation.y += delta
  }
})

Without using delta, the animation speed would vary depending on the frame rate, leading to inconsistent behavior across different devices, like the example below:

60fps
  ::examples-basic-animation-60fps
  ::

  <div class="p-2 text-center p-2 border-b border-gray-200 font-bold">
     120fps
  </div>

  ::examples-basic-animation-120fps
  ::

The value of delta is 0.016 for 60fps and 0.008 for 120fps, this difference ensures that the cube rotates at the same speed on both frame rates.

Using elapsed

The onBeforeRender callback also provides an elapsed parameter, which represents the total time elapsed since the start of the animation. This can be useful for creating time-based animations like oscillations.

onBeforeRender(({ elapsed }) => {
  if (cubeRef.value) {
    cubeRef.value.position.y += Math.sin(elapsed) * 0.01
  }
})

::examples-basic-animation-elapsed ::