什么是PixiJS
PixiJS是一个用于2D游戏和交互式应用程序开发的快速、轻量级、模块化的JavaScript库。和大多数其他的2D游戏库不同,它是用JavaScript编写的,并以WebGL作为渲染器。PixiJS允许开发者使用WebGL硬件加速功能,加速游戏渲染。
(在不支持WebGL的浏览器中会自动回退到Canvas)
PixiJS和Canvas
在开发过程中,使用PixiJS和Canvas渲染生成Dom元素均为canvas标签,Canvas更适用于一些简单的2D图形绘制,而PixiJS则更适用于开发复杂的2D应用,比如交互更加复杂的小游戏。主要有以下几点不同
渲染方式不同
Canvas是基于像素进行渲染的,而PixiJS是基于WebGL技术进行渲染的,因此PixiJS在性能上要远远超过Canvas。
常见形状实现方式不同
使用Canvas想要绘制各种形状,需要手动绘制它们。而使用PixiJS,则可以通过使用现成的形状对象,例如矩形、圆形等等,使得绘图变得更加容易。
下面是一个绘制矩形的例子,使用canvas绘制需要先在模版中创建一个容器,再进行绘制,并且代码易读性差,而PixiJs更贴近我们日常开发思维。
使用canvas
<template>
<canvas id="canvas" :width="50" :height="100"></canvas>
</template>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.rect(0, 0, 50, 100);
ctx.fillStyle = 'red';
ctx.fill();
PixiJS
import * as PIXI from 'pixi.js';
const app = new PIXI.Application({ width: 50, height: 100 });
document.body.appendChild(app.view);
const rectangle = new PIXI.Graphics();
rectangle.beginFill('blue');
rectangle.drawRect(0, 0, 50, 100);
rectangle.endFill();
app.stage.addChild(rectangle);
app作为一个应用程序,app.stage则是负责渲染canvas的容器(舞台)
源代码:stackblitz.com/edit/pixijs…
支持程度不同:
Canvas虽然能够进行基本的2D绘图,但它缺少一些高级图形和渲染功能;而PixiJS则具有更多的高级功能支持,例如自动图集、骨骼动画、多重混合和过滤器等,感兴趣的读者可自行查阅。
开发复杂度不同
使用Canvas需要开发人员手动处理各个元素,并及时清除部分重绘,这一过程较为繁琐。而使用PixiJS,通过使用精灵等可缓存渲染对象,可以使得开发更加简单和高效。此外,PixiJS也具有多种工具和插件,可以帮助开发人员提升开发效率。
常用API
PIXI.Application
const app = new PIXI.Application({
width: 800, // 宽度
height: 600, // 高度
transparent: false, // 是否透明
resolution: 1 // 缩放比例,默认为1
});
PIXI.Application
会创建一个应用程序实例,可以使用它提供的方法和属性来创建和管理 PIXI.js 应用程序,例如添加场景、渲染显示对象等。
以上代码不需要提前创建容器,你也可以通过指定
view
属性使其在现有的canvas上工作。
PIXI.Sprite
PIXI.Sprite
类代表了我们所看到的大多数图像,它负责将纹理(Texture)渲染到屏幕上,也就是图片资源。
const app = new PIXI.Application({
resizeTo: window,
});
document.body.appendChild(app.view);
let texture = PIXI.Texture.from('src/assets/vue.svg');
let sprite = new PIXI.Sprite(texture);
app.stage.addChild(sprite);
绘制结果如下
PIXI.Graphics
PIXI.Graphics
类允许我们创建任何形状,比如线条、圆形和矩形等
绘制线条
let graphics = new PIXI.Graphics();
graphics.lineStyle(1, 0xFF3300, 1); // 设置线条的样式,4是线条宽度,0xFF3300是颜色, 1是透明度
graphics.moveTo(0, 0); // 设置线条的起点
graphics.lineTo(50, 200); // 设置线条的终点
绘制圆形
graphics.beginFill(0xFF0000); // 设置填充颜色为红色
graphics.drawCircle(100, 100, 50); // 绘制圆形,100分别为X轴和Y轴的坐标,50为半径
graphics.endFill(); // 停止填充
绘制椭圆
50和80分别为水平、垂直半径
let graphics = new PIXI.Graphics();
graphics.beginFill(0xFF0000);
graphics.drawEllipse(100, 100, 50, 80); // 绘制椭圆
graphics.endFill();
上述代码中,
lineStyle
方法用于设置线条的样式,
moveTo
和 lineTo
方法用于绘制线条,
beginFill
方法用于开始填充,
drawCircle
和 drawRect
方法用于绘制圆形和矩形,drawEllipse
用于绘制椭圆
endFill
方法用于停止填充。
该部分案例效果在这里
可拖拽矩形绘制
创建矩形
import * as PIXI from 'pixi.js';
// 创建应用程序
const app = new PIXI.Application({
width: 400,
height: 400,
backgroundColor: 0x1099bb
});
// 添加画布到DOM
document.body.appendChild(app.view);
// 创建矩形图形
const rect = new PIXI.Graphics();
rect.beginFill(0xff0000);
rect.drawRect(0, 0, 100, 100);
rect.endFill();
rect.interactive = true;
rect.buttonMode = true;
其中,PIXI.Graphics
的interactive属性设置为true表示这个矩形元素可以交互,比如拖拽,点击等
注册事件
// 注册鼠标事件
rect
.on('pointerdown', onDragStart)
.on('pointerup', onDragEnd)
.on('pointerupoutside', onDragEnd);
// 添加矩形到舞台
app.stage.addChild(rect);
-
pointerdown
事件在用户按下鼠标按钮或移动端触摸交互元素时触发。 -
pointerup
事件在用户释放鼠标按钮或结束移动端触摸交互元素时触发。 -
pointerupoutside
事件在用户释放鼠标按钮或结束移动端触摸,但是鼠标指针不再在 PIXI.Graphics 对象内部时触发。
实时更新位置
// 记录鼠标位置和矩形位置偏移
let dragData = null;
let offset = null;
function onDragStart(event) {
dragData = event.data;
offset = dragData.getLocalPosition(this);
this.ticker = app.ticker.add(() => onDragMove.call(this));
}
// 更新矩形位置
function onDragMove() {
// 增加判断防止元素为null报错
if (dragData) {
const newPosition = dragData.getLocalPosition(this.parent);
this.position.x = newPosition.x - offset.x;
this.position.y = newPosition.y - offset.y;
}
}
// 清除鼠标位置和位置偏移
function onDragEnd() {
dragData = null;
offset = null;
if (this.ticker) {
app.ticker.remove(this.ticker);
this.ticker = null;
}
}
当按下鼠标左键时,会执行 onDragStart 函数,这个函数会记录鼠标位置和偏移量,并在 app.ticker 中注册 onDragMove 函数;当用户释放鼠标左键时,会执行 onDragEnd 函数,这个函数会清除记录的数据,并停止更新矩形位置;如果在释放鼠标按钮时鼠标指针不在矩形内部,则也会执行 onDragEnd 函数。
完整效果在这