tempus means time in Latin, this package is a lightweight, high-performance animation frame manager for JavaScript applications.
- 🚀 Merge multiple requestAnimationFrame loops for better performance
- 🎯 Control execution priority of different animations
- ⚡ Support for custom frame rates (FPS)
- 🔄 Compatible with popular animation libraries
- 🪶 Zero dependencies
- 📦 ~1KB gzipped
using package manager
npm install tempusimport Tempus from 'tempus'using script tag
<script src="https://unpkg.com/[email protected]/dist/tempus.min.js"></script> import Tempus from "tempus"
// Simple animation at maximum FPS
function animate(time, deltaTime) {
console.log('frame', time, deltaTime)
}
Tempus.add(animate)const unsubscribe = Tempus.add(animate)
unsubscribe()Tempus.pause() // no rafs will be called
Tempus.play() // resume
Tempus.restart() // set clock elapsed time to 0See tempus/react
Tempus.add(animate, {
fps: 30 // Will run at 30 FPS
})
Tempus.add(animate, {
fps: '50%' // Will run at 50% of the system's FPS
})——[-Infinity]——[0]——[Infinity]——> execution order
// Default priority: 0 (runs second)
Tempus.add(() => console.log('animate'))
// Priority: 1 (runs third)
Tempus.add(() => console.log('render'), { priority: 1 })
// Priority: -1 (runs first)
Tempus.add(() => console.log('scroll'), { priority: -1 })scroll
animate
render
idle callback will only run when the usage is less than the idle percentage in order to not block the main thread. It's useful for optional background tasks.
Tempus.add(() => console.log('idle'), { idle: 0.8 }) // will only run when the raf usage is less than 80%ping and pong will alternate between each frame, but never during the same frame
let framesCount = 0
Tempus.add(() => {
if (framesCount === 0) {
console.log('ping')
} else {
console.log('pong')
}
framesCount++
framesCount %= 2
})// Patch native requestAnimationFrame across all your app
Tempus.patch()
// Now any requestAnimationFrame recursive calls will use TempusTempus.add(lenis.raf)// Remove GSAP's internal RAF
gsap.ticker.remove(gsap.updateRoot)
// Add to Tempus
Tempus.add((time) => {
gsap.updateRoot(time / 1000)
})Tempus.add(() => {
renderer.render(scene, camera)
}, { priority: 1 })
// the render will happen after other rafs
// so it can be synched with lenis for instanceAdds an animation callback to the loop.
- callback:
(time: number, deltaTime: number, frameCount: number) => void - options:
priority:number(default: 0) - Lower numbers run firstfps:number(default: Infinity) - Target frame rate
- Returns:
() => void- Unsubscribe function
Patches the native requestAnimationFrame to use Tempus.
Unpatches the native requestAnimationFrame to use the original one.
- Use priorities wisely: critical animations (like scroll) should have higher priority
- Clean up animations when they're no longer needed
- Consider using specific FPS for non-critical animations to improve performance (e.g: collisions)
- Use Ping Pong technique for heavy computations running concurrently
MIT © darkroom.engineering
Thank you to Keith Cirkel for having transfered us the npm package name 🙏.
