title: Basic Animations description: Learn how to create basic animations in TresJS
::examples-basic-animation ::
This recipe covers the fundamentals of creating smooth animations in TresJS.
::steps
useLoop
composableThe 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"} ::
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. ::
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:
::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
::
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.
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 ::