Table of contents
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Animation
Any numeric filter parameter can be animated, except construction options (see Filter Specs). Animations are part of the saved spec, under animated, keyed by parameter name:
await leanFX.addUpdateFiltersOnSelected([{
filterType: "glow", filterId: "pulse", color: 0xff3300, distance: 12,
animated: {
outerStrength: {animType: "cosOscillation", loopDuration: 2000, val1: 1, val2: 6},
color: {animType: "colorOscillation", loopDuration: 4000, val1: 0xff3300, val2: 0xffcc00}
}
}]);
A filter can animate up to 16 parameters. Colors need a color mode (colorOscillation, halfColorOscillation, syncColorOscillation, randomColor, randomColorPerLoop). Booleans and stack fields (padding, gridPadding, zOrder) cannot be animated.
Options
| Option | Default | Meaning |
|---|---|---|
animType |
required | The mode, see below. |
active |
true |
false pauses this animation and leaves the parameter at its spec value. |
loopDuration |
3000 |
Length of one loop in milliseconds (16 ms to 24 h). |
loops |
null |
Number of loops; null repeats forever. A finite animation stops on its last value and stays there. |
pauseBetweenDuration |
0 |
Pause after each loop, in milliseconds. |
val1, val2 |
0 |
The two values oscillations and random modes move between. |
speed |
0 |
For move: units per millisecond (negative values count down). |
syncShift |
0 |
Phase offset as a fraction of a loop: 0.5 is half a loop ahead. |
clockWise |
true |
Rotation direction. |
chaosFactor |
0.25 |
Irregularity of the chaotic modes, 0–1. |
wantInteger |
false |
Round the value down to an integer. |
Modes
| Mode | Value over time |
|---|---|
move |
The parameter's spec value plus speed × elapsed milliseconds. The usual way to run a shader's time. |
moveToward |
From val1 to val2 within each loop, linearly. |
cosOscillation |
Smoothly from val1 to val2 and back, once per loop. Starts at val1. |
sinOscillation |
The same, starting halfway between the two values. |
halfCosOscillation, halfSinOscillation |
Half a wave per loop: val1 to val2 in one loop, back in the next. With loops: 1 it is a one-way transition. |
colorOscillation |
Like cosOscillation, blending each RGB channel. |
halfColorOscillation |
Like halfCosOscillation, for colors. |
chaoticOscillation |
cosOscillation with an irregular phase set by chaosFactor. |
rotation |
Degrees through a full turn per loop (0→360); counter-clockwise gives 360→0. |
randomNumber |
A new random value between val1 and val2 thirty times a second. |
randomNumberPerLoop |
A new random value between val1 and val2 once per loop. |
randomColor |
A random color thirty times a second. |
randomColorPerLoop |
A random color once per loop. |
syncCosOscillation, syncSinOscillation, syncColorOscillation, syncChaoticOscillation, syncRotation |
The same as the modes without sync, but the phase comes from a shared clock instead of the filter's start time: all filters with the same loopDuration move in step, even when created at different times. Use syncShift to offset one. |
Random values are the same on every client.
Timing
Each filter remembers when it was created. Every client computes the current value from that moment and the active GM's shared clock, so animations stay in step between players and continue after a reload or a late join; a slow frame catches up instead of drifting. The GM republishes the server-start offset on ready and election, including short restarts. Players trust the published offset despite their own wall-clock skew; without a GM, clients estimate time locally. Finite animations show their final value by default. No per-frame document writes occur.
- Updating a filter's other parameters (or
enabled) keeps its timeline. - Updating
animatedreplaces all of the filter's animations and starts them from the beginning. animated: {}stops all animations; the parameters return to their spec values.
One-shot completion
Add onComplete: "delete" at the filter-spec level to dispose the rendered filter and delete its saved entry after the last active animation ends. "hold" is the default. Delete-on-completion requires at least one active animation and finite loops on every active property; inactive properties do not delay removal.
Each property's end is (loops - 1) * (loopDuration + pauseBetweenDuration) + loopDuration milliseconds after creation. The longest decides the filter's deadline. enabled: false does not pause it.
The active GM cleans up saved entries across all scenes, even with no canvas viewed, and catches up on ready/reconnect. Clients skip expired filters on redraw and dispose late-arriving textures. With no GM, rendering still expires locally while saved entries wait for the next GM. Background throttling may delay the saved write. Cleanup re-reads the current spec/start inside the document queue, so an old deadline cannot delete a newly replayed effect with the same ID.
Use addUpdateFilters to replay a one-shot. Replacing animated restarts its lifetime; other edits retain it. To turn it into a static filter, update with onComplete: "hold" and animated: {}. One-shot previews restore saved effects when their last filter expires. See the hit flash example.
Units to keep in mind
rotation produces degrees, which fits rotation parameters in degrees (transform, sprite, spriteMask, bevel, drop shadow). Some parameters take radians instead (twist angle, twAngle, distortion maskSpriteRotation, dot angle); animate those with an oscillation between radian values. The filter pages give each parameter's unit.
Disabling animations
Each user can turn on Disable effect animations in the module settings. Animated effects then show a still frame on that client: finite animations at their end state, endless ones at the moment they were drawn. Other players are not affected.
One-shots retain deadline checking and still disappear at their normal end time.