我正在参与「码上挑战赛」概略请看:码上挑战赛来了!
介绍
本期将用 pixi.js 来完结一个水波交互动画,里面包含了水体曲解和点击水波分散的效果,主要利用了 pixi.js 库以及关于它的 filters
滤镜的运用。
演示
正文
基础建立
安装 pixi.js 库:
# NPM
npm i pixi.js -S
# Yarn
yarn add pixi.js
引进并初始化:
import * as PIXI from "pixi.js"
const GAME_WIDTH = 1920;
const GAME_HEIGHT = 1080;
export default class Game {
constructor(el) {
return this.init(el)
}
init(el) {
// 初始化
this.app = new PIXI.Application({
width: GAME_WIDTH,
height: GAME_HEIGHT,
});
el.appendChild(this.app.view);
this.loader = new PIXI.Loader();
this.loader
.add("bg", "assets/waterwave_0.jpg")
.add("wave", "assets/waterwave_1.jpg")
.load(this.render.bind(this))
return this;
}
render(loader, resources) {
// 烘托
}
}
初始化便是创立 pixi.js 运用,然后把生成后的视图追加到要传入的 el 元素节点上。这儿我们还要先加载两张图片,一张为水体布景,另一张为水体曲解的错位图。加载完这两种图后,我们才会实行 render
方法进行烘托。
水体曲解
import * as PIXI from "pixi.js"
const GAME_WIDTH = 1920;
const GAME_HEIGHT = 1080;
export default class Game {
// ...
render(loader, resources) {
// 烘托
this.resources = resources;
const bg = PIXI.Sprite.from(resources.bg.texture);
bg.anchor.set(0.5);
bg.position.set(GAME_WIDTH / 2, GAME_HEIGHT / 2)
bg.scale.set(.5, .5)
this.container = new PIXI.Container();
this.container.interactive = true;
this.container.buttonMode = true;
this.container.addChild(bg);
this.app.stage.addChild(this.container);
}
}
当然在做曲解效果之前,我们先要把刚才加载好的水体布景制作到界面上。
export default class Game {
// ...
render(loader, resources) {
// ...
this.container.filters = []
this.displacementSprite = new PIXI.Sprite.from(resources.wave.texture)
this.displacementSprite.texture.baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT;
this.displacementSprite.scale.set(1);
const displacementFilter = new PIXI.filters.DisplacementFilter(this.displacementSprite);
this.container.addChild(this.displacementSprite);
this.container.filters.push(displacementFilter)
this.app.ticker.add(this.step.bind(this));
}
step() {
const { displacementSprite } = this;
displacementSprite.x += 1.7;
if (displacementSprite.x >= displacementSprite.width) {
displacementSprite.x = 0;
}
}
}
这儿我们用了 pixi.js 内置的过滤器类 DisplacementFilter
,它的效果是做贴图置换,做纹理偏移。
先实例化一个 DisplacementFilter
类,把纹理错位图传入进去,然后把这个过滤器实例添加到 filters
数组里面,最终实行 ticker
在 step
方法里会接二连三的实行, 经过不断改动 x 轴坐标,来完结纹理偏移水体曲解的效果。
水波动画
我们还要再引进一个 pixi.js 的一个插件库 pixi-filters.js ,它可以处理很多的过滤器效果,水波便是其间一个。
import "./pixi-filters"
export default class Game {
// ...
render(loader, resources) {
// ...
this.shockwaveFilters = []
this.container.on('pointerdown', (e) => {
const { x, y } = e.data.global
const shockwaveFilter = new PIXI.filters.ShockwaveFilter(
[x, y],
{
amplitude: 20 + 20 * Math.random(), // 振幅
wavelength: 30 + 10 * Math.random(), // 波长
speed: 100 + 100 * Math.random(), // 速度
radius: 80 * Math.random() + 120, // 半径
},
0
)
this.shockwaveFilters.push(shockwaveFilter)
this.container.filters.push(shockwaveFilter)
});
}
step() {
// ...
const { shockwaveFilters } = this;
for (let i = 0; i < shockwaveFilters.length; i++) {
const filter = shockwaveFilters[i];
filter.time += .008;
if (filter.time >= 2) {
shockwaveFilters.splice(i, 1)
i--
}
}
}
}
引进 pixi-filters.js 库后,我们就可以用它实例化一个 ShockwaveFilter
类来完结波纹效果,具体来说,便是在点击屏幕容器的时分,会实例化ShockwaveFilter
类,其间可以随机传入振幅、波长、速度、半径等参数,目的是为了让每次点击水波效果都有些许差异。再将这个过滤器添加一个单独的数组中保存,一同还要添加到 filters
中,在 step
方法不断实行的时分,我们就要遍历这个 shockwaveFilters
数组,将它的 time
特点累加就会发生水波效果动画了。可是别忘了,它实行完之后还要记住移除掉,防止占用内存空间。