Appearance
Timelines
While a single animation moves properties from one state to another, a Timeline lets you group multiple animations, labels, and callbacks together in order.
Timelines make it easy to play things one after another without guessing delay times. The timeline calculates the total time automatically, letting you easily pause, play, reverse, or skip around the entire sequence.
Basic sequencing
By default, animations added to a timeline play one after another. An animation will wait for the previous one to finish before starting.
Instead of using AnimX.animate(), you call the identical .animate() method directly on your timeline instance:
js
const tl = AnimX.timeline()
tl.animate('.box', { x: 200, duration: 0.6 })
tl.animate('.box', { y: 100, duration: 0.6 }) // starts after x finishesThe timeline automatically calculates its total duration based on its children.
The position parameter
Playing things one after another isn't always enough. Sometimes you need animations to overlap or start at the exact same time.
The position parameter (the third argument in .animate()) lets you control exactly when an animation starts in the timeline.
0s
1s
2s
3s
4s
default
'<'
'>'
'+=0.4'
'<+=0.5'
0.5
'>+=0.5'
There are three ways to define a position:
1. Absolute time (number) Insert the animation at exactly N seconds from the start of the timeline.
js
tl.animate('.box', { x: 100 }, 1.5) // always starts at 1.5s2. Relative to the end of everything (+=) If you don't provide a position (or use +=), the animation looks at all previous animations and waits until the longest running animation finishes.
For example, imagine you add two animations:
Animation 1runs from0sto10s.Animation 2runs from2sto8s.
Even though Animation 2 was the last one you typed in the code, the latest active time is still 10s (from Animation 1). Therefore, using += will wait for that 10-second mark.
js
tl.animate('.box', { x: 100 }, '+=1') // waits for the 10s mark, then adds 1s (starts at 11s)
tl.animate('.box', { y: 100 }, '-=0.5') // waits for the 10s mark, then subtracts 0.5s (starts at 9.5s)3. Relative to the previous sibling (< and >) The < symbol aligns the current animation with the start of the previously added sibling animation. The > symbol aligns the current animation with the end of the previously added sibling animation.
Think of < and > as pointing to the left (start) or right (end) of the animation directly above it in your code.
You can also combine these with offsets to add or subtract time.
js
tl.animate('.b1', { x: 100 }) // Animation 1
tl.animate('.b2', { x: 100 }, '<') // Starts exactly when Animation 1 starts
tl.animate('.b3', { x: 100 }, '>') // Starts exactly when Animation 2 ends
tl.animate('.b4', { x: 100 }, '>+=0.5') // Starts 0.5s AFTER Animation 3 ends
tl.animate('.b5', { x: 100 }, '<+=0.5') // Starts 0.5s AFTER Animation 4 starts
tl.animate('.b6', { x: 100 }, 0.5) // Starts exactly at 0.5 seconds into the timelineQuick summary of `+=` vs `>`
>looks only at the animation directly above it. (In the example above, it would look atAnimation 2and start at8s).+=looks at every animation added so far, and waits for the longest one to finish. (In the example above, it waits forAnimation 1and starts at10s).
Labels and callbacks
Labels are bookmarks for specific points in your timeline. They let you reference a specific time without hardcoding exact seconds.
You can add a label at the current time using addLabel(). You can then use this label as the position parameter for other animations so they start at the exact same time.
Additionally, callbacks let you run your own JavaScript code at a specific point in the timeline.
In the demo below, watch how the text highlights exactly when the moving dot passes the markers.
'halfway' label
end callback
js
const tl = AnimX.timeline()
// 1. Move to 150px
tl.animate('.dot', { x: 150, duration: 1 })
// 2. Drop a label here
tl.addLabel('halfway')
// 3. Fire a one-off callback (triggers when playing forward)
tl.call(() => console.log('Passed the halfway mark!'))
// 4. Animate the label with a tiny duration so it scrubs perfectly in both directions
tl.animate('.log1', { opacity: 1, color: '#00d4ff', duration: 0.01 }, '<')
// 5. Continue moving to 300px
tl.animate('.dot', { x: 300, duration: 1 })
tl.call(() => console.log('End reached!'))
tl.animate('.log2', { opacity: 1, color: '#00d4ff', duration: 0.01 }, '<')
// You can jump to a label later:
// tl.seek('halfway').call(callback, params, position)
The .call() method executes a custom function at a specific point in your timeline.
Arguments:
callback(Function): The function to execute.params(Array, optional): An array of arguments to pass to your callback function.position(String | Number, optional): Exactly when the callback should fire. Follows the exact same Positioning rules as.animate()(e.g.<,>,+=0.5, etc.). By default, it appends to the end of the timeline.
js
// Fire exactly 2 seconds into the timeline
tl.call(() => console.log('2 seconds passed!'), [], 2)
// Pass arguments to the callback, firing immediately after the previous animation
tl.call((name, status) => {
console.log(`${name} is ${status}`)
}, ['AnimX', 'Awesome'], '>')NOTE
Callbacks only run when playing forward; they do not automatically "undo" anything when playing backward.
Also, .call() does not implicitly pass the timeline instance into your parameter array. However, this is automatically bound to the Timeline instance, meaning you can access properties like this.progress or this.duration directly inside your callback (so long as you use function() {} and not an arrow function).
Best Practice
If you are changing visual styles (like display: none or changing colors), use a 0-duration .apply() or .animate() instead of .call(). This allows AnimX to automatically revert the style changes when the timeline plays in reverse! Use .call() only for external side-effects like playing audio, sending analytics data, or triggering other game logic.
Nesting timelines
You can put timelines inside other timelines. This is great for keeping your code organized.
You can create functions that return small timelines, and add those directly to a master timeline.
js
function createIntro() {
const tl = AnimX.timeline()
tl.animate('.logo', { y: 0, opacity: 1 })
return tl
}
function createOutro() {
const tl = AnimX.timeline()
tl.animate('.logo', { opacity: 0 })
return tl
}
// Master sequence controls everything
const master = AnimX.timeline()
master.add(createIntro())
master.add(createOutro(), '+=2') // wait 2 seconds before the outroChild timelines automatically follow the play/pause state, speed, and direction of their parent.
Timeline options
When creating a timeline, you can pass a configuration object to set its playback behavior. It accepts many of the same flags as a standard tween.
js
const tl = AnimX.timeline({
paused: true, // wait for tl.play()
repeat: -1, // loop forever (-1)
yoyo: true, // alternate direction on each repeat
repeatDelay: 1, // wait 1 second between repeats
delay: 0.5, // wait 0.5 seconds before starting the first time
ease: 'power2.inOut' // applies easing to the timeline's overall progress!
})If you add an ease to a timeline, it curves the flow of time for the entire sequence. Everything inside it will subtly speed up and slow down.
API Reference
Constructor
js
const tl = AnimX.timeline(options)| Option | Type | Default | Description |
|---|---|---|---|
paused | boolean | false | If true, the timeline will not start playing automatically. |
repeat | number | 0 | Number of times to loop (-1 for infinite). |
yoyo | boolean | false | If true, reverses playback direction on every other repeat cycle. |
delay | number | 0 | Initial delay before starting the first cycle (in seconds). |
repeatDelay | number | 0 | Delay between loop cycles (in seconds). |
ease | string | Function | null | A timeline-level ease applied to the total duration playback. |
onStart | Function | null | Fired when the timeline begins playing. |
onUpdate | Function | null | Fired every frame while the timeline is active. |
onComplete | Function | null | Fired when the timeline finishes. |
Instance Methods
All methods that add animations return the timeline instance (this), allowing you to chain them: tl.animate(...).addLabel(...).animate(...).
| Method | Description |
|---|---|
animate(targets, vars, position) | Works like AnimX.animate(). Adds an animation to the timeline. |
animateFrom(targets, vars, position) | Works like AnimX.animateFrom(). Adds a 'from' animation. |
sequence(targets, from, to, position) | Works like AnimX.sequence(). Adds a 'from-to' animation. |
apply(targets, vars, position) | Works like AnimX.apply(). Adds an instant change. |
add(child, position) | Adds an existing Tween, Timeline, Function, or label string. |
addLabel(name, position) | Inserts a named label at the given position. |
call(fn, params, position) | Inserts a zero-duration callback. |
remove(child) | Removes a specific child and recalculates total duration. |
clear(labels) | Empties all children. Pass false to keep labels intact. |
Playback Methods
| Method | Description |
|---|---|
play(from) | Starts or resumes playback. Optionally provide a time/label to start from. |
pause(atTime) | Pauses playback. |
reverse(from) | Plays backwards. |
seek(timeOrLabel) | Jumps to a specific time (in seconds) or a label string. |
kill() | Stops the timeline completely and cleans it up from memory. |
Properties
| Property | Type | Description |
|---|---|---|
progress | number | Get or set the playback progress (0 to 1). Setting this seeks the timeline. |
timeScale | number | Get or set the playback speed multiplier. 1 is normal, -1 is reverse. |
totalDuration | number | The absolute length of the timeline (in seconds), including repeats. |