Vue 3 Recipe • Production Motion Pattern

Vue Use Animation Frame: High-Performance 60/120fps Render Loops in Vue 3

Writing manual requestAnimationFrame loops inside Vue 3 components is notoriously error-prone: forgetting to cancel loops on unmount causes silent background CPU leaks, while computing state changes inside the loop often triggers cascade re-renders across the Vue component tree. The ExodeUI useAnimationFrame composable offers a clean, declarative solution tailored to modern Vue architecture. It automatically binds to the browser monitor refresh rate (60Hz, 120Hz, 144Hz ProMotion), tracks high-resolution delta timestamps, and guarantees foolproof lifecycle cleanup the exact moment your Vue component unmounts.

Vue 3 Live Interactive Stage
exodeui-vue
TICK COUNT1813
TARGET FPS60 / 120 FPS
DELTA TIMING16.6 ms
Synchronized directly before display repaint
Under the Hood: Vue 3 Reactivity & WebGL Pipeline

ExodeUI for Vue connects Vue 3 reactive ref and computed primitives directly to GPU uniform registers and state machines, eliminating Virtual DOM recalculation overhead and guaranteeing consistent 120fps motion.

Runnable ExodeUI Vue 3 Code Example

Vue 3 SFC Composition API

Import the ExodeUICanvas component and bind reactive parameters declaratively without imperative DOM lifecycle hooks:

html
<template>
  <div class="fps-stage">
    <div class="metrics-card">
      <span>Render Tick: {{ tickCount }}</span>
      <span>Delta Time: {{ deltaFormatted }} ms</span>
      <span>Effective FPS: {{ currentFPS }}</span>
    </div>

    <ExodeUICanvas
      ref="canvasRef"
      src="/scenes/vue-raf-sine-wave.json"
      :inputs="{ 'elapsedTime': totalElapsed }"
    />
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';
import { ExodeUICanvas, useAnimationFrame } from 'exodeui-vue';

const tickCount = ref(0);
const delta = ref(16.6);
const totalElapsed = ref(0);

const deltaFormatted = computed(() => delta.value.toFixed(2));
const currentFPS = computed(() => (1000 / (delta.value || 16.6)).toFixed(0));

// ExodeUI handles automatic registration and onUnmounted teardown
useAnimationFrame(({ deltaMs, elapsedTime }) => {
  tickCount.value += 1;
  delta.value = deltaMs;
  totalElapsed.value = elapsedTime / 1000;
});
</script>

Frequently Asked Questions about vue use animation frame

Does useAnimationFrame automatically cancel the loop when navigating away?

Yes. The composable hooks into Vue onUnmounted and automatically calls cancelAnimationFrame, eliminating memory leaks when users switch views.

Does useAnimationFrame pause when the browser tab is in the background?

Yes. Modern browser tab throttling automatically suspends requestAnimationFrame, and ExodeUI guards against large delta time spikes upon tab refocus.

How is useAnimationFrame superior to setInterval for animations in Vue?

setInterval fires independently of the monitor refresh rate, causing frame tearing and stutter. useAnimationFrame fires directly before screen repaint at the native display Hz.

Explore Related Vue Recipes & Documentation Hubs