PixiJS 滤镜效果 #
滤镜概述 #
PixiJS 提供了强大的滤镜系统,可以为显示对象添加各种视觉效果。
text
┌─────────────────────────────────────────────────────────────┐
│ 滤镜系统 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 内置滤镜 │
│ ├── BlurFilter(模糊) │
│ ├── ColorMatrixFilter(颜色矩阵) │
│ ├── DisplacementFilter(位移) │
│ ├── NoiseFilter(噪点) │
│ └── AlphaFilter(透明度) │
│ │
│ 扩展滤镜(pixi-filters) │
│ ├── GlowFilter(发光) │
│ ├── OutlineFilter(描边) │
│ ├── DropShadowFilter(投影) │
│ ├── TwistFilter(扭曲) │
│ └── 更多特效滤镜 │
│ │
│ 自定义滤镜 │
│ └── 使用 GLSL 着色器 │
│ │
└─────────────────────────────────────────────────────────────┘
基本使用 #
应用滤镜 #
javascript
import { BlurFilter } from 'pixi.js';
const sprite = PIXI.Sprite.from('image.png');
// 应用单个滤镜
sprite.filters = [new BlurFilter()];
// 应用多个滤镜
sprite.filters = [
new BlurFilter(),
new ColorMatrixFilter()
];
移除滤镜 #
javascript
// 移除所有滤镜
sprite.filters = null;
// 移除特定滤镜
sprite.filters = sprite.filters.filter(f => !(f instanceof BlurFilter));
内置滤镜 #
BlurFilter(模糊) #
javascript
import { BlurFilter } from 'pixi.js';
const blurFilter = new BlurFilter();
// 设置模糊强度
blurFilter.blur = 5; // 统一设置
blurFilter.blurX = 5; // 水平模糊
blurFilter.blurY = 5; // 垂直模糊
// 模糊质量
blurFilter.quality = 4; // 1-10,越高越慢
sprite.filters = [blurFilter];
ColorMatrixFilter(颜色矩阵) #
javascript
import { ColorMatrixFilter } from 'pixi.js';
const colorMatrix = new ColorMatrixFilter();
// 预设效果
colorMatrix.night(); // 夜景
colorMatrix.predator(); // 掠食者视觉
colorMatrix.lsd(); // 迷幻效果
colorMatrix.kodachrome(); // 柯达胶片
colorMatrix.polaroid(); // 拍立得
colorMatrix.technicolor(); // 彩色技术
colorMatrix.browni(); // 棕褐色
colorMatrix.vintage(); // 复古
colorMatrix.colorTone(0.2, 0.88, 0x339900, 0.001); // 色调
colorMatrix.desaturate(); // 去色
colorMatrix.greyscale(0.5); // 灰度
colorMatrix.hue(90); // 色相旋转
colorMatrix.contrast(0.5); // 对比度
colorMatrix.brightness(0.5); // 亮度
colorMatrix.saturate(0.5); // 饱和度
sprite.filters = [colorMatrix];
自定义颜色矩阵 #
javascript
const colorMatrix = new ColorMatrixFilter();
// 手动设置矩阵
colorMatrix.matrix = [
1, 0, 0, 0, 0, // R
0, 1, 0, 0, 0, // G
0, 0, 1, 0, 0, // B
0, 0, 0, 1, 0 // A
];
// 矩阵说明:
// [R', G', B', A', Offset]
// R' = R*r0 + G*r1 + B*r2 + A*r3 + r4
// G' = R*g0 + G*g1 + B*g2 + A*g3 + g4
// B' = R*b0 + G*b1 + B*b2 + A*b3 + b4
// A' = R*a0 + G*a1 + B*a2 + A*a3 + a4
NoiseFilter(噪点) #
javascript
import { NoiseFilter } from 'pixi.js';
const noiseFilter = new NoiseFilter();
// 噪点强度(0-1)
noiseFilter.noise = 0.5;
sprite.filters = [noiseFilter];
DisplacementFilter(位移) #
javascript
import { DisplacementFilter, Sprite } from 'pixi.js';
// 创建位移贴图
const displacementSprite = Sprite.from('displacement-map.png');
displacementSprite.texture.baseTexture.wrapMode = 'repeat';
const displacementFilter = new DisplacementFilter(displacementSprite);
// 位移强度
displacementFilter.scale.x = 50;
displacementFilter.scale.y = 50;
sprite.filters = [displacementFilter];
// 动态效果
app.ticker.add(() => {
displacementSprite.x += 1;
displacementSprite.y += 1;
});
AlphaFilter(透明度) #
javascript
import { AlphaFilter } from 'pixi.js';
const alphaFilter = new AlphaFilter();
// 设置透明度
alphaFilter.alpha = 0.5;
sprite.filters = [alphaFilter];
pixi-filters 扩展 #
安装 #
bash
npm install pixi-filters
GlowFilter(发光) #
javascript
import { GlowFilter } from 'pixi-filters';
const glowFilter = new GlowFilter({
distance: 15, // 发光距离
outerStrength: 2, // 外发光强度
innerStrength: 0, // 内发光强度
color: 0x00ff00, // 发光颜色
quality: 0.5 // 质量(0-1)
});
sprite.filters = [glowFilter];
OutlineFilter(描边) #
javascript
import { OutlineFilter } from 'pixi-filters';
const outlineFilter = new OutlineFilter({
thickness: 2, // 描边宽度
color: 0xff0000 // 描边颜色
});
sprite.filters = [outlineFilter];
DropShadowFilter(投影) #
javascript
import { DropShadowFilter } from 'pixi-filters';
const shadowFilter = new DropShadowFilter({
offset: { x: 4, y: 4 }, // 偏移
color: 0x000000, // 颜色
alpha: 0.5, // 透明度
blur: 4, // 模糊
quality: 4 // 质量
});
sprite.filters = [shadowFilter];
TwistFilter(扭曲) #
javascript
import { TwistFilter } from 'pixi-filters';
const twistFilter = new TwistFilter({
offset: { x: 0.5, y: 0.5 }, // 扭曲中心
radius: 200, // 扭曲半径
angle: 60 // 扭曲角度
});
sprite.filters = [twistFilter];
BulgePinchFilter(凸起/捏合) #
javascript
import { BulgePinchFilter } from 'pixi-filters';
const bulgeFilter = new BulgePinchFilter({
center: [0.5, 0.5], // 中心点(0-1)
radius: 200, // 半径
strength: 0.5 // 强度(正数凸起,负数捏合)
});
sprite.filters = [bulgeFilter];
PixelateFilter(像素化) #
javascript
import { PixelateFilter } from 'pixi-filters';
const pixelateFilter = new PixelateFilter({
size: 8 // 像素大小
});
sprite.filters = [pixelateFilter];
RadialBlurFilter(径向模糊) #
javascript
import { RadialBlurFilter } from 'pixi-filters';
const radialBlurFilter = new RadialBlurFilter({
angle: 5, // 模糊角度
center: [0.5, 0.5], // 中心点
kernelSize: 5, // 内核大小
radius: 0.5 // 半径
});
sprite.filters = [radialBlurFilter];
ShockwaveFilter(冲击波) #
javascript
import { ShockwaveFilter } from 'pixi-filters';
const shockwaveFilter = new ShockwaveFilter({
center: [0.5, 0.5], // 中心点
amplitude: 10, // 振幅
wavelength: 100, // 波长
brightness: 1.5, // 亮度
speed: 200, // 速度
radius: 200 // 半径
});
sprite.filters = [shockwaveFilter];
滤镜动画 #
动态模糊 #
javascript
const blurFilter = new BlurFilter();
sprite.filters = [blurFilter];
let direction = 1;
let blurAmount = 0;
app.ticker.add(() => {
blurAmount += 0.1 * direction;
if (blurAmount >= 10) direction = -1;
if (blurAmount <= 0) direction = 1;
blurFilter.blur = blurAmount;
});
颜色过渡 #
javascript
const colorMatrix = new ColorMatrixFilter();
sprite.filters = [colorMatrix];
let hue = 0;
app.ticker.add(() => {
hue = (hue + 1) % 360;
colorMatrix.hue(hue);
});
位移波浪 #
javascript
const displacementSprite = Sprite.from('displacement-map.png');
displacementSprite.texture.baseTexture.wrapMode = 'repeat';
const displacementFilter = new DisplacementFilter(displacementSprite);
sprite.filters = [displacementFilter];
let count = 0;
app.ticker.add(() => {
count += 0.05;
displacementSprite.x = Math.sin(count) * 20;
displacementSprite.y = Math.cos(count) * 20;
displacementFilter.scale.x = Math.sin(count) * 30 + 30;
displacementFilter.scale.y = Math.cos(count) * 30 + 30;
});
发光脉冲 #
javascript
import { GlowFilter } from 'pixi-filters';
const glowFilter = new GlowFilter({
distance: 15,
outerStrength: 2,
color: 0x00ff00
});
sprite.filters = [glowFilter];
let pulse = 0;
app.ticker.add(() => {
pulse += 0.05;
glowFilter.outerStrength = 2 + Math.sin(pulse) * 1.5;
});
自定义滤镜 #
创建自定义滤镜 #
javascript
import { Filter } from 'pixi.js';
const fragmentShader = `
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
uniform float uTime;
void main(void) {
vec2 uv = vTextureCoord;
// 波浪效果
uv.x += sin(uv.y * 10.0 + uTime) * 0.01;
uv.y += cos(uv.x * 10.0 + uTime) * 0.01;
gl_FragColor = texture2D(uSampler, uv);
}
`;
const customFilter = new Filter(null, fragmentShader, {
uTime: { type: 'f32', value: 0 }
});
sprite.filters = [customFilter];
// 更新 uniform
app.ticker.add((ticker) => {
customFilter.uniforms.uTime += ticker.deltaTime * 0.1;
});
传递参数 #
javascript
const fragmentShader = `
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
uniform vec3 uColor;
uniform float uIntensity;
void main(void) {
vec4 color = texture2D(uSampler, vTextureCoord);
// 混合颜色
color.rgb = mix(color.rgb, uColor, uIntensity);
gl_FragColor = color;
}
`;
const colorTintFilter = new Filter(null, fragmentShader, {
uColor: { type: 'vec3<f32>', value: [1, 0, 0] }, // 红色
uIntensity: { type: 'f32', value: 0.5 }
});
sprite.filters = [colorTintFilter];
// 动态更新颜色
colorTintFilter.uniforms.uColor = [0, 1, 0]; // 改为绿色
colorTintFilter.uniforms.uIntensity = 0.8;
顶点着色器 #
javascript
const vertexShader = `
attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat3 projectionMatrix;
uniform float uTime;
varying vec2 vTextureCoord;
void main(void) {
vTextureCoord = aTextureCoord;
vec2 position = aVertexPosition;
// 波浪变形
position.y += sin(position.x * 0.05 + uTime) * 10.0;
gl_Position = vec4((projectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);
}
`;
const fragmentShader = `
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
void main(void) {
gl_FragColor = texture2D(uSampler, vTextureCoord);
}
`;
const waveFilter = new Filter(vertexShader, fragmentShader, {
uTime: { type: 'f32', value: 0 }
});
实战示例 #
按钮悬停效果 #
javascript
import { GlowFilter } from 'pixi-filters';
class GlowButton extends Container {
constructor(text, width, height) {
super();
this.background = new Graphics();
this.background.roundRect(0, 0, width, height, 8);
this.background.fill({ color: 0x3366cc });
this.label = new Text({
text,
style: { fontFamily: 'Arial', fontSize: 18, fill: 0xffffff }
});
this.label.anchor.set(0.5);
this.label.x = width / 2;
this.label.y = height / 2;
this.addChild(this.background, this.label);
this.eventMode = 'static';
this.cursor = 'pointer';
this.glowFilter = new GlowFilter({
distance: 10,
outerStrength: 0,
color: 0xffffff
});
this.on('pointerover', () => this.onOver());
this.on('pointerout', () => this.onOut());
}
onOver() {
this.filters = [this.glowFilter];
gsap.to(this.glowFilter, {
outerStrength: 2,
duration: 0.3
});
}
onOut() {
gsap.to(this.glowFilter, {
outerStrength: 0,
duration: 0.3,
onComplete: () => {
this.filters = null;
}
});
}
}
场景切换效果 #
javascript
class SceneTransition {
constructor(app) {
this.app = app;
this.container = new Container();
this.container.sortableChildren = true;
this.overlay = new Graphics();
this.overlay.rect(0, 0, app.screen.width, app.screen.height);
this.overlay.fill({ color: 0x000000 });
this.overlay.alpha = 0;
this.overlay.zIndex = 1000;
this.container.addChild(this.overlay);
app.stage.addChild(this.container);
}
async fadeOut(duration = 0.5) {
return new Promise((resolve) => {
gsap.to(this.overlay, {
alpha: 1,
duration,
onComplete: resolve
});
});
}
async fadeIn(duration = 0.5) {
return new Promise((resolve) => {
gsap.to(this.overlay, {
alpha: 0,
duration,
onComplete: resolve
});
});
}
async transition(newScene, duration = 0.5) {
await this.fadeOut(duration);
// 切换场景
await this.fadeIn(duration);
}
}
水波纹效果 #
javascript
import { ShockwaveFilter } from 'pixi-filters';
class WaterRipple {
constructor(app) {
this.app = app;
this.filters = [];
app.stage.eventMode = 'static';
app.stage.hitArea = app.screen;
app.stage.on('pointerdown', (event) => {
this.createRipple(event.global.x, event.global.y);
});
}
createRipple(x, y) {
const filter = new ShockwaveFilter({
center: [x / this.app.screen.width, y / this.app.screen.height],
amplitude: 10,
wavelength: 50,
brightness: 1,
speed: 500,
radius: -1
});
this.filters.push(filter);
this.app.stage.filters = this.filters;
// 动画完成后移除
gsap.to(filter, {
amplitude: 0,
duration: 2,
onComplete: () => {
const index = this.filters.indexOf(filter);
if (index > -1) {
this.filters.splice(index, 1);
}
if (this.filters.length === 0) {
this.app.stage.filters = null;
}
}
});
}
}
热扭曲效果 #
javascript
class HeatDistortion {
constructor(sprite) {
this.sprite = sprite;
const displacementSprite = Sprite.from('noise.png');
displacementSprite.texture.baseTexture.wrapMode = 'repeat';
this.displacementFilter = new DisplacementFilter(displacementSprite);
this.displacementSprite = displacementSprite;
sprite.filters = [this.displacementFilter];
this.time = 0;
}
update(delta) {
this.time += delta * 0.02;
this.displacementSprite.x = Math.sin(this.time) * 100;
this.displacementSprite.y = Math.cos(this.time * 0.8) * 100;
this.displacementFilter.scale.x = 5 + Math.sin(this.time * 2) * 2;
this.displacementFilter.scale.y = 5 + Math.cos(this.time * 2) * 2;
}
}
性能优化 #
滤镜性能影响 #
text
┌─────────────────────────────────────────────────────────────┐
│ 滤镜性能影响 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 性能消耗排序(从低到高) │
│ │
│ 1. AlphaFilter - 极低 │
│ 2. ColorMatrixFilter - 低 │
│ 3. NoiseFilter - 低 │
│ 4. BlurFilter - 中(取决于质量和大小) │
│ 5. DisplacementFilter - 中 │
│ 6. GlowFilter - 高 │
│ 7. OutlineFilter - 高 │
│ 8. 自定义滤镜 - 取决于着色器复杂度 │
│ │
└─────────────────────────────────────────────────────────────┘
优化建议 #
javascript
// 1. 减少滤镜数量
// 不推荐
sprite.filters = [
new BlurFilter(),
new GlowFilter(),
new ColorMatrixFilter(),
new NoiseFilter()
];
// 推荐:合并效果
const colorMatrix = new ColorMatrixFilter();
colorMatrix.brightness(0.2);
sprite.filters = [colorMatrix];
// 2. 使用滤镜区域
const blurFilter = new BlurFilter();
blurFilter.blur = 5;
blurFilter.padding = 10; // 减少计算区域
// 3. 缓存静态滤镜效果
sprite.filters = [new BlurFilter()];
sprite.cacheAsBitmap = true;
// 4. 按需启用滤镜
if (sprite.visible && sprite.alpha > 0) {
sprite.filters = [blurFilter];
} else {
sprite.filters = null;
}
滤镜池 #
javascript
class FilterPool {
constructor() {
this.pools = new Map();
}
get(FilterClass, options = {}) {
const key = FilterClass.name + JSON.stringify(options);
if (!this.pools.has(key)) {
this.pools.set(key, []);
}
const pool = this.pools.get(key);
if (pool.length > 0) {
return pool.pop();
}
return new FilterClass(options);
}
release(filter) {
const key = filter.constructor.name;
if (!this.pools.has(key)) {
this.pools.set(key, []);
}
this.pools.get(key).push(filter);
}
}
const filterPool = new FilterPool();
// 使用
const blurFilter = filterPool.get(BlurFilter, { blur: 5 });
sprite.filters = [blurFilter];
// 释放
filterPool.release(blurFilter);
sprite.filters = null;
下一步 #
掌握了滤镜效果后,接下来学习 高级主题,了解性能优化、最佳实践等高级内容!
最后更新:2026-03-29