
R3f Animation
Wire up motion in React Three Fiber scenes—per-frame updates, GLTF clips, springs, and keyframes—without guessing Three.js/R3F APIs.
Overview
r3f-animation is an agent skill for the Build phase that teaches React Three Fiber animation with useFrame, useAnimations, spring physics, and keyframes.
Install
npx skills add https://github.com/enzed/r3f-skills --skill r3f-animationWhat is this skill?
- useFrame loop with state, delta, and optional xrFrame for every-frame mesh and camera updates
- Documented state object fields: clock, camera, scene, gl, and mouse for time- and input-driven motion
- Quick-start Canvas + RotatingBox pattern for immediate procedural rotation
- Coverage of useAnimations, spring physics, and keyframes for GLTF clips and smoothed movement
- Procedural motion recipes for objects that are not driven by baked model animations
- useFrame runs on every render frame with state and delta (seconds since last frame)
- Documented state fields include clock, camera, scene, gl, and mouse
- Quick-start covers Canvas, ambientLight, mesh ref, and dual-axis rotation rates
Adoption & trust: 661 installs on skills.sh; 89 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You have a React Three Fiber scene but no clear pattern for frame-synced rotation, GLTF clips, or smooth physics-based movement.
Who is it for?
Solo builders already using @react-three/fiber who need procedural motion, model animations, or spring-smoothed transforms in a React codebase.
Skip if: Teams building flat 2D-only UIs, native mobile 3D outside the browser, or projects that will not adopt React and WebGL.
When should I use this skill?
Use when animating objects, playing GLTF animations, creating procedural motion, or implementing physics-based movement.
What do I get? / Deliverables
You get copy-ready R3F animation components with correct useFrame loops and hook-based GLTF or spring motion wired into your Canvas.
- useFrame animation components with delta-time-correct rotation or translation
- GLTF animation wiring via useAnimations patterns
- Spring- or keyframe-driven motion snippets ready to paste into R3F trees
Recommended Skills
Journey fit
How it compares
Use instead of dropping raw Three.js AnimationMixer tutorials into R3F components without useFrame and useAnimations lifecycle patterns.
Common Questions / FAQ
Who is r3f-animation for?
r3f-animation is for solo and indie developers shipping interactive 3D in React—product demos, mini-games, creative sites, and agent-assisted refactors of existing Canvas code.
When should I use r3f-animation?
Use it during Build → frontend when you need per-frame motion (useFrame), GLTF clip playback, keyframed parameters, or spring-based movement in a React Three Fiber app.
Is r3f-animation safe to install?
Treat it like any third-party skill: review the Security Audits panel on this Prism page and inspect the SKILL.md in your repo before granting agent file or network access.
SKILL.md
READMESKILL.md - R3f Animation
# React Three Fiber Animation ## Quick Start ```tsx import { Canvas, useFrame } from '@react-three/fiber' import { useRef } from 'react' function RotatingBox() { const meshRef = useRef() useFrame((state, delta) => { meshRef.current.rotation.x += delta meshRef.current.rotation.y += delta * 0.5 }) return ( <mesh ref={meshRef}> <boxGeometry /> <meshStandardMaterial color="hotpink" /> </mesh> ) } export default function App() { return ( <Canvas> <ambientLight /> <RotatingBox /> </Canvas> ) } ``` ## useFrame Hook The core animation hook in R3F. Runs every frame. ### Basic Usage ```tsx import { useFrame } from '@react-three/fiber' import { useRef } from 'react' function AnimatedMesh() { const meshRef = useRef() useFrame((state, delta) => { // state contains: clock, camera, scene, gl, mouse, etc. // delta is time since last frame in seconds meshRef.current.rotation.y += delta }) return ( <mesh ref={meshRef}> <boxGeometry /> <meshStandardMaterial color="orange" /> </mesh> ) } ``` ### State Object ```tsx useFrame((state, delta, xrFrame) => { const { clock, // THREE.Clock camera, // Current camera scene, // Scene gl, // WebGLRenderer mouse, // Normalized mouse position (-1 to 1) pointer, // Same as mouse viewport, // Viewport dimensions size, // Canvas size raycaster, // Raycaster get, // Get current state set, // Set state invalidate, // Request re-render (when frameloop="demand") } = state // Time-based animation const t = clock.getElapsedTime() meshRef.current.position.y = Math.sin(t) * 2 }) ``` ### Render Priority ```tsx // Lower numbers run first. Default is 0. // Use negative for pre-render, positive for post-render function PreRender() { useFrame(() => { // Runs before main render }, -1) } function PostRender() { useFrame(() => { // Runs after main render }, 1) } function DefaultRender() { useFrame(() => { // Runs at default priority (0) }) } ``` ### Conditional Animation ```tsx function ConditionalAnimation({ isAnimating }) { const meshRef = useRef() useFrame((state, delta) => { if (!isAnimating) return meshRef.current.rotation.y += delta }) return <mesh ref={meshRef}>...</mesh> } ``` ## GLTF Animations with useAnimations The recommended way to play animations from GLTF/GLB files. ### Basic Usage ```tsx import { useGLTF, useAnimations } from '@react-three/drei' import { useEffect, useRef } from 'react' function AnimatedModel() { const group = useRef() const { scene, animations } = useGLTF('/models/character.glb') const { actions, names } = useAnimations(animations, group) useEffect(() => { // Play first animation actions[names[0]]?.play() }, [actions, names]) return <primitive ref={group} object={scene} /> } ``` ### Animation Control ```tsx function Character() { const group = useRef() const { scene, animations } = useGLTF('/models/character.glb') const { actions, mixer } = useAnimations(animations, group) useEffect(() => { const action = actions['Walk'] if (action) { // Playback control action.play() action.stop() action.reset() action.paused = true // Speed action.timeScale = 1.5 // 1.5x speed action.timeScale = -1 // Reverse // Loop modes action.loop = THREE.LoopOnce action.loop = THREE.LoopRepeat action.loop = THREE.LoopPingPong action.repetitions = 3 action.clampWhenFinished = true // Weight (for blending)