Animate PixiJS Filter Properties Over Time
This article explains how to animate the internal properties and custom uniforms of filters in Pixi.js using the application loop. You will learn how to set up an animation ticker, access filter properties, and update them incrementally over time to create dynamic visual effects like pulsing blurs or custom shader distortions.
Using the PixiJS Ticker
The standard way to animate properties in Pixi.js is through the
Ticker class. The ticker runs an update loop on every frame
(typically 60 frames per second) and provides a delta time value to
ensure smooth animations regardless of frame rate fluctuations.
To animate a filter, you instantiate the filter, apply it to a container or sprite, and then modify the filter’s properties inside the ticker listener.
Animating Built-in Filters
For built-in filters, you can directly access and modify their public
properties (such as blur, noise, or
red) inside the loop.
import * as PIXI from 'pixi.js';
// 1. Initialize the PixiJS Application
const app = new PIXI.Application();
await app.init({ width: 800, height: 600 });
document.body.appendChild(app.canvas);
// 2. Create a sprite and apply a BlurFilter
const sprite = PIXI.Sprite.from('path/to/image.png');
const blurFilter = new PIXI.BlurFilter();
sprite.filters = [blurFilter];
app.stage.addChild(sprite);
// 3. Create an animation variable
let elapsed = 0;
// 4. Update the filter property in the ticker loop
app.ticker.add((ticker) => {
// Increment elapsed time based on delta time
elapsed += ticker.deltaTime * 0.05;
// Animate the blur property using a sine wave for a pulsing effect
blurFilter.blur = (Math.sin(elapsed) + 1) * 10;
});Animating Custom Filter Uniforms
If you are using a custom shader (via PIXI.Filter or
PIXI.Shader), you animate the internal properties by
updating the filter’s uniforms object. This is highly
useful for passing a time variable to a fragment shader.
// Define custom fragment shader code
const fragmentShader = `
precision mediump float;
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
uniform float uTime;
void main(void) {
vec2 uv = vTextureCoord;
// Create a waving wave effect using the uTime uniform
uv.x += sin(uv.y * 10.0 + uTime) * 0.02;
gl_FragColor = texture2D(uSampler, uv);
}
`;
// Create a custom filter with default uniforms
const customFilter = new PIXI.Filter({
glProgram: PIXI.GlProgram.from({
vertex: PIXI.defaultVertex,
fragment: fragmentShader,
}),
resources: {
timeUniforms: {
uTime: { value: 0, type: 'f32' },
}
}
});
sprite.filters = [customFilter];
let totalTime = 0;
app.ticker.add((ticker) => {
// Increment time
totalTime += ticker.deltaTime * 0.02;
// Update the custom uniform inside the shader
customFilter.resources.timeUniforms.uTime = totalTime;
});By utilizing PixiJS’s app.ticker, you can smoothly
transition any internal filter value, enabling complex visual states and
rendering effects.