@zakkster/lite-timeline
v1.0.1
Published
Zero-GC sequence runner with GSAP-style positioning. Chain timed callbacks, easing, reverse, seek, loop. The glue between UI and VFX.
Maintainers
Readme
@zakkster/lite-timeline
Zero-GC sequence runner with GSAP-style positioning. The glue between UI animations and VFX.
Why lite-timeline?
| Feature | lite-timeline | GSAP | anime.js | Popmotion | |---|---|---|---|---| | Zero-GC | Yes | No | No | No | | Shared Ticker | Yes | Own loop | Own loop | Own loop | | GSAP-style positions | +=, -=, <, > | Full | No | No | | Seek / Scrub | Yes | Yes | No | No | | Reverse | Yes | Yes | Yes | No | | Loop | Yes | Yes | Yes | No | | Duration-zero events | Yes | Yes | No | No | | Ref-counted ticker | Yes | No | No | No | | Bundle size | < 2KB | ~25KB | ~12KB | ~5KB | | License | MIT | Paid for commercial | MIT | MIT |
Installation
npm install @zakkster/lite-timelineQuick Start
import { createTimeline } from '@zakkster/lite-timeline';
import { easeOut } from '@zakkster/lite-lerp';
const tl = createTimeline();
tl.add({ duration: 500, ease: easeOut, onUpdate: t => {
modal.style.opacity = t;
modal.style.transform = `scale(${0.8 + t * 0.2})`;
}})
.add({ duration: 0, onComplete: () => particles.burst() })
.add({ duration: 800, ease: easeOut, onUpdate: t => {
text.style.opacity = t;
}}, '+=200')
.play();Recipes
const tl = createTimeline({ onComplete: () => console.log('done') });
tl.add({ duration: 500, ease: easeOut, onUpdate: t => {
modal.style.opacity = t;
modal.style.transform = `scale(${lerp(0.8, 1, t)})`;
}})
.add({ duration: 0, onComplete: () => confetti.burst({ y: 200 }) })
.add({ duration: 800, ease: easeInOut, onUpdate: t => {
winText.style.transform = `translateY(${lerp(20, 0, t)}px)`;
}}, '+=200')
.play();const cards = document.querySelectorAll('.card');
const tl = createTimeline();
cards.forEach((card, i) => {
tl.add({ duration: 400, ease: easeOut, onUpdate: t => {
card.style.opacity = t;
card.style.transform = `translateY(${lerp(30, 0, t)}px)`;
}}, i * 80); // Absolute offset: each card 80ms apart
});
tl.play();const tl = createTimeline();
tl.add({ duration: 300, ease: easeOut, onUpdate: t => {
card.style.transform = `scale(${lerp(1, 1.05, t)})`;
card.style.boxShadow = `0 ${lerp(4, 20, t)}px ${lerp(10, 40, t)}px rgba(0,0,0,${lerp(0.1, 0.3, t)})`;
}});
card.addEventListener('mouseenter', () => tl.play());
card.addEventListener('mouseleave', () => tl.reverse());API
| Method | Description |
|---|---|
| createTimeline(options?) | Create a timeline. Options: onComplete, loop, ticker |
| .add(config, position?) | Add a track. Config: duration, onUpdate, onComplete, ease |
| .play() | Play forward. Auto-resets if at end. |
| .reverse() | Play backward. |
| .pause() | Pause at current time. |
| .seek(ms) | Jump to time and evaluate all tracks. |
| .reset() | Return to beginning. |
| .duration | Total duration (ms). |
| .time | Current time (ms). |
| .progress | Current progress (0-1). |
| .destroy() | Clean up. Releases shared ticker ref. |
Position strings: '+=200' (200ms after last), '-=100' (100ms overlap), '<' (same start as previous), '>' (same end as previous), or absolute number.
License
MIT
