Skip to content

darkroomengineering/tempus

Repository files navigation

Tempus

TEMPUS

Introduction

tempus means time in Latin, this package is a lightweight, high-performance animation frame manager for JavaScript applications.

Packages

Features

  • πŸš€ 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

Installation

using package manager

npm install tempus
import Tempus from 'tempus'

using script tag

<script src="https://unpkg.com/tempus@1.0.0-dev.11/dist/tempus.min.js"></script> 

Basic Usage

import Tempus from "tempus"

// Simple animation at maximum FPS
function animate(time, deltaTime) {
  console.log('frame', time, deltaTime)
}

Tempus.add(animate)

Cleanup

const unsubscribe = Tempus.add(animate)

unsubscribe()

React

See tempus/react

Advanced Usage

Custom Frame Rates

Tempus.add(animate, { 
  fps: 30 // Will run at 30 FPS
})

Tempus.add(animate, { 
  fps: '50%' // Will run at 50% of the system's FPS
})

Priority System

β€”β€”[-Infinity]β€”β€”[0]β€”β€”[Infinity]β€”β€”> execution order

Input

// 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 })

Output

scroll
animate
render

Global RAF Patching

// Patch native requestAnimationFrame across all your app
Tempus.patch()
// Now any requestAnimationFrame recursive calls will use Tempus

Ping Pong Technique

let framesCount = 0

// ping and pong will run at 50% of the system's FPS,
// but never during the same frame
Tempus.add(() => {
  if (framesCount === 0) {
    console.log('ping')
  } else {
    console.log('pong')
  }

  framesCount++
  framesCount %= 2
})

Integration Examples

With Lenis Smooth Scroll

Tempus.add(lenis.raf)

With GSAP

// Remove GSAP's internal RAF
gsap.ticker.remove(gsap.updateRoot)

// Add to Tempus
Tempus.add((time) => {
  gsap.updateRoot(time / 1000)
})

With Three.js

Tempus.add(() => {
  renderer.render(scene, camera)
}, { priority: 1 })
// the render will happen after other rafs
// so it can be synched with lenis for instance

API Reference

Tempus.add(callback, options)

Adds an animation callback to the loop.

  • callback: (time: number, deltaTime: number) => void
  • options:
    • priority: number (default: 0) - Lower numbers run first
    • fps: number (default: Infinity) - Target frame rate
  • Returns: () => void - Unsubscribe function

Tempus.patch()

Patches the native requestAnimationFrame to use Tempus.

Tempus.unpatch()

Unpatches the native requestAnimationFrame to use the original one.

Best Practices

  • 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.

License

MIT Β© darkroom.engineering

Shoutout

Thank you to Keith Cirkel for having transfered us the npm package name πŸ™.