Animate React Three Fiber objects with useFrame, damping, and GLTF clips. Use for procedural motion, animation transitions, or demand-loop animation; use physics guidance for collision-driven movement.
Install
npx skills add https://github.com/enzed/r3f-skills --skill r3f-animationSKILL.md
React Three Fiber animation
Check installed Fiber, Drei, and React versions first. These examples target Fiber 9 / React 19. Keep the project's animation library when it already meets the task.
Choose an owner
- Use
useFrameand refs for continuous transforms/uniforms; React state describes discrete goals such as selected, open, or active. - Use Drei
useAnimationsfor authored GLTF clips. Read clip playback for independent animated instances and cleanup. - Use the project's spring/tween library for coordinated transitions; check its React peer dependencies before adding it. Do not introduce a state manager merely to animate a mesh.
- Let Rapier own simulated body transforms. Animate kinematic targets through physics APIs rather than fighting the simulation with mesh positions.
Damping that can return to idle
Mount below Canvas; this also works with frameloop="demand". Click the box to change its target.
import { useEffect, useRef, useState } from 'react'
import { useFrame, useThree } from '@react-three/fiber'
import { MathUtils, type Mesh } from 'three'
export default function Example() {
const mesh = useRef<Mesh>(null)
const [active, setActive] = useState(false)
const invalidate = useThree((state) => state.invalidate)
const target = active ? 1 : -1
useEffect(() => { invalidate() }, [target, invalidate])
useFrame((_, delta) => {
if (!mesh.current) return
// Cap a visual transition's resume jump, not a physics simulation step.
const x = MathUtils.damp(mesh.current.position.x, target, 6, Math.min(delta, 0.1))
const moving = Math.abs(x - target) > 0.001
mesh.current.position.x = moving ? x : target
if (moving) invalidate()
})
return (
<mesh ref={mesh} name="moving-box" onClick={() => setActive((value) => !value)}>
<boxGeometry />
<meshStandardMaterial color={active ? 'orange' : 'coral'} />
</mesh>
)
}
Timing and performance
deltais seconds. Integrate velocity asposition += velocity * delta; useMathUtils.dampor lerp with1 - exp(-lambda * delta)for exponential smoothing. A fixed lerp fraction depends on refresh rate;delta * speedcan overshoot.- Reuse vectors/quaternions; avoid allocating them in every frame. Use quaternion interpolation for orientation instead of independently lerping Euler angles across wrap boundaries.
- Use one timeline/clock owner. Fiber 9 still supplies
state.clock; do not replace Fiber internals because Three.js deprecated new standaloneClockinstances. For independent Three.js timing, consultTimerin the installed release. - On demand, external animation systems need invalidation while active. Invalidate before starting a synchronous animation and arrange the start on the next frame if the first frame would otherwise jump.
- Read fast external state directly in the frame callback when supported (e.g. a store's
getState()); subscribe React only to UI-relevant changes. Clean up external subscriptions. - Do not claim a normal React re-render stops animation. Profile actual work and subscription frequency before memoizing components.
- Hiding an object does not stop its frame callback or mixer. Pause expensive animation explicitly when appropriate; respect reduced-motion preferences for decorative motion.
- Repeated oscillations and shader motion can derive phase from elapsed time; simulations needing reproducibility require a fixed-step design, not arbitrary delta clamping.
Verify
Compare motion at different frame rates, background/resume behavior, and repeated target changes. On demand, confirm the object wakes, reaches its goal, and stops requesting frames. For clips, test two instances playing different actions.
Sources
Related skills
vercel-react-best-practicesvercel-labs751KReact and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.vercel-composition-patternsvercel-labs361KReact composition patterns that scale. Use when refactoring components with boolean prop proliferation, building flexible component libraries, or designing reusable APIs. Triggers on tasks involving compound components, render props, context providers, or component architecture. Includes React 19 API changes.vercel-react-view-transitionsvercel-labs135KGuide for implementing smooth, native-feeling animations using React's View Transition API (`<ViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter/exit of components, animate list reorder, implement directional (forward/back) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions viewpick-ui-libraryemilkowalski124KPick the right library for a given frontend task from a curated, opinionated list — numbers, OTP inputs, charts, command menus, virtualization, drag and drop, toasts, state, styling, and more. Only runs when explicitly invoked; it does not trigger on its own.