pixi实现波浪水滴特效

458 阅读2分钟

实现效果

image.png

第1步 导入pixi

import * as PIXI from "pixi.js";
import {ShockwaveFilter} from "pixi-filters";   //水波纹滤镜

第2步 创建一个画布并设置

let app = new PIXI.Application({
  width: window.innerWidth,
  height: window.innerHeight,
  backgroundColor: 0xffffff,
  resolution: window.devicePixelRatio || 1, //设备像素比
});

第3步 将画布添加到页面上

相当于创建一个canvas画布

document.body.appendChild(app.view);

第4步 创建纹理(加载图片)

纹理存储表示图像或图像的一部分的信息。 它不能直接添加到显示列表中;而是将其用作Sprite的纹理。如果没有为纹理提供框架,则使用整个图像。

const texture = PIXI.Texture.from("./textures/car.jpg");  //它基于你提供的源创建一个新的纹理,将图片传给Sprite

第5步 创建精灵

Sprite对象是渲染到屏幕上的所有纹理对象的基础

const spirte = new PIXI.Sprite(texture);    //Sprite把texture渲染到屏幕上
spirte.width = app.screen.width;
spirte.height = app.screen.height;

第6步 创建容器(可不要容器)

它是所有显示对象的基类,充当其他对象的容器,包括图形和精灵。 后续都所有的都添加到容器上。

const container = new PIXI.Container();
container.addChild(spirte);
app.stage.addChild(container);  //容器添加到画布上

第7步 创建文字

文本是使用Canvas API创建的,缺点是每个文本都有自己的纹理,这会占用更多的内存。当文本发生变化时,这个纹理必须重新生成并重新上传到GPU,这占用了时间。

const text = new PIXI.Text('hello world',{        
  fontFamily: "Arial",  
  fontSize: 30+Math.floor(app.screen.width  * 0.1),
  fill: 0xffffff,                 //画布填充样式
  align: "center",                //对齐
  dropShadow: true,               //设置阴影
  dropShadowColor: "000000",      //设置阴影颜色
  dropShadowBlur: 4,              //阴影模糊度
  dropShadowAngle: Math.PI / 2,   //阴影角度
  dropShadowDistance: 2,          //阴影强度
});
text.x = app.screen.width / 2;
text.y = app.screen.height / 2;
text.anchor.set(0.5);              //文本锚点
container.addChild(text);

第8步 添加置换滤镜

const displacement = PIXI.Sprite.from('./textures/displacement.jpg');
displacement.scale.set(0.5);                                         //放大缩小
displacement.texture.baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT;  //允许纹理重复模式
const displacementFilter = new PIXI.DisplacementFilter(displacement);
container.addChild(displacement);

第9步 添加水波纹滤镜

const shockwaveFilter1 = new ShockwaveFilter(
  [Math.random() * app.screen.width, Math.random() * app.screen.height],  //随机的宽高
  {
    radius: 40,        //半径
    waveLength: 30,    //波长
    amplitude: 10,     //振幅  
    speed:200,         //扩散速度
  },
  0                   //从0开始,还未扩散
);
const shockwaveFilter2 = new ShockwaveFilter(
  [Math.random() * app.screen.width, Math.random() * app.screen.height],
  {
    radius: 100,        //半径
    waveLength: 45,     //波长
    amplitude: 80,      //振幅  
    speed:240,          //扩散速度
  },
  0                     //从0开始,还未扩散
);
const shockwaveFilter3 = new ShockwaveFilter(
  [Math.random() * app.screen.width, Math.random() * app.screen.height],
  {
    radius: 160,        //半径
    waveLength: 65,     //波长
    amplitude: 105,     //振幅  
    speed:300,          //扩散速度
  },
  0                     //从0开始,还未扩散
);
container.filters = [displacementFilter,shockwaveFilter1,shockwaveFilter2,shockwaveFilter3];

第10步 实现动画效果

app.ticker.add((delta) => {
  displacement.x += 1 *delta;
  displacement.y += 1;
  createWave(shockwaveFilter1, 1);  //随机生成3个波纹
  createWave(shockwaveFilter2, 1.2);
  createWave(shockwaveFilter3, 0.7);
})

第11步 创建生成波纹

function createWave(waveFilter, resetTime) {
  waveFilter.time += 0.01;
  if (waveFilter.time > resetTime) {
    waveFilter.time = 0;
    waveFilter.center = [
      Math.random() * app.screen.width,
      Math.random() * app.screen.height
    ];
  }
}

第12步 实现点击出现水波纹

// 监听点击事件
app.view.addEventListener('click', (e) => {
  shockwaveFilter3.center = [e.clientX, e.clientY];
  shockwaveFilter3.time = 0;
})