PixiJS是一個輕量級的2D渲染引擎,它能自動偵測使用WebGL仍是Canvas來建立圖形。這個庫常常被用來製做HTML5遊戲以及有複雜交互的H5活動頁。javascript
注意:本文使用pixi最新的v5版本,同時使用Parcel進行模塊化打包html
項目初始化前端
mkdir learn-pixi
cd learn-pixi
npm init -y
複製代碼
安裝依賴java
npm i pixi.js -save
npm i parcel-bundler -save-dev
複製代碼
根目錄建立index.html
git
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>learn-pixi</title>
</head>
<body>
<script src="./src/index.js"></script>
</body>
</html>
複製代碼
根目錄建立src
目錄,新建src/index.js
github
alert('pixi');
複製代碼
修改package.json
web
"scripts": {
"dev": "parcel index.html -p 8080",
"build": "parcel build index.html"
}
複製代碼
運行npm run dev
,訪問 http://localhost:8080/ 便可看到效果npm
index.js
json
import { Application } from 'pixi.js';
const app = new Application({
width: 300,
height: 300,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x1d9ce0
});
// app.view就是個canvas元素,掛載到頁面上
document.body.appendChild(app.view);
複製代碼
頁面上就出現了一個300*300的藍色矩形,矩形是由pixi.js建立的canvas渲染的。 canvas
咱們能夠繼續建立新的圖形,而後渲染到canvas裏
import { Application, Graphics } from 'pixi.js';
const app = new Application({
width: 300,
height: 300,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x1d9ce0
});
document.body.appendChild(app.view);
// 建立一個半徑爲32px的圓
const circle = new Graphics();
circle.beginFill(0xfb6a8f);
circle.drawCircle(0, 0, 32);
circle.endFill();
circle.x = 130;
circle.y = 130;
// 添加到app.stage裏,從而能夠渲染出來
app.stage.addChild(circle);
複製代碼
咱們還能夠渲染圖片
import { Application, Sprite } from 'pixi.js';
const app = new Application({
width: 300,
height: 300,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x1d9ce0
});
document.body.appendChild(app.view);
// 建立一個圖片精靈
const avatar = new Sprite.from('http://anata.me/img/avatar.jpg');
// 圖片寬高縮放0.5
avatar.scale.set(0.5, 0.5);
app.stage.addChild(avatar);
複製代碼
咱們讓這個圖片精靈變得能夠交互:點擊圖片後,圖片透明度變成0.5
const avatar = new Sprite.from('http://anata.me/img/avatar.jpg');
avatar.scale.set(0.5, 0.5);
// 居中展現
avatar.x = 100;
avatar.y = 100;
// 可交互
avatar.interactive = true;
// 監聽事件
avatar.on('click', () => {
// 透明度
avatar.alpha= 0.5;
})
app.stage.addChild(avatar);
複製代碼
咱們還能讓圖片一直旋轉
const avatar = new Sprite.from('http://anata.me/img/avatar.jpg');
avatar.scale.set(0.5, 0.5);
avatar.x = 150;
avatar.y = 150;
// 修改旋轉中心爲圖片中心
avatar.anchor.set(0.5, 0.5)
app.stage.addChild(avatar);
app.ticker.add(() => {
// 每秒調用該方法60次(60幀動畫)
avatar.rotation += 0.01;
})
複製代碼
pixi
有幾個重要的Class:
const app = new Application({
width: 300,
height: 300
});
複製代碼
Application
是pixi提供的一個工具方法,它能自動建立renderer,ticker 和container,咱們一般使用該方法快速建立應用。
app.stage
是一個Container
的實例,做爲最底層的舞臺(stage),全部要渲染的圖形都應放在它的內部
const app = new Application({
width: 300,
height: 300
});
// 添加不一樣的圖形
app.stage.addChild(circle1);
app.stage.addChild(circle2);
複製代碼
咱們也能夠建立本身的Container
,自定義的Container一般用來分組
import { Application, Container, Graphics } from 'pixi.js';
const app = new Application({
width: 300,
height: 300,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x1d9ce0
});
// 自定義Container
const myContainer = new Container();
// 相對於根節點偏移
myContainer.position.set(40, 40);
let rectangle = new Graphics();
rectangle.beginFill(0x000000);
rectangle.drawRect(0, 0, 64, 64);
rectangle.endFill();
let rectangle2 = new Graphics();
rectangle2.beginFill(0xFFFFFF);
rectangle2.drawRect(0, 0, 64, 64);
rectangle2.endFill();
// 相對於自定義Container偏移
rectangle2.position.set(20, 20);
// 兩個圖形加到自定義Container裏
myContainer.addChild(rectangle);
myContainer.addChild(rectangle2);
// 自定義Container最後須要添加到app.stage
app.stage.addChild(myContainer);
document.body.appendChild(app.view);
複製代碼
分組的好處在於,修改container的屬性,位於其中的子節點,都會受到影響。好比上面的例子,咱們把rectangle
和rectangle2
分到了同一個組裏,若是但願同時隱藏這兩個元素,只需修改它們父級container的透明度便可。
// 父級透明,則子級也透明
myContainer.alpha = 0;
複製代碼
一種常見的作法是,咱們建立一個最頂層的rootContainer
,以後全部的內容,都添加到rootContainer
裏。而rootContainer
做爲頂級元素,能夠進行一些縮放來適配不一樣的分辨率:
const rootContainer = new Container();
app.stage.addChild(rootContainer);
// 相對於設計稿750px進行縮放(豎屏狀態)
const screenScaleRito = window.innerWidth / 750; // 橫屏則用innerHeight
rootContainer.scale.set(screenScaleRito, screenScaleRito);
複製代碼
這種方法相似咱們前端的rem佈局
app.renderer
是一個Renderer
的實例,若是你但願從新渲染頁面,就須要使用它
// 把畫布從新渲染爲500*500大小
app.renderer.resize(500, 500);
// 渲染一個容器
const container = new Container();
app.renderer.render(container);
複製代碼
Sprite精靈,你能夠把它當作普通的矢量圖形,只不過它是根據圖片渲染出來的。
const avatar = new Sprite.from('http://anata.me/img/avatar.jpg');
// 和普通的圖形同樣能夠設置各類屬性
avatar.width = 100;
avatar.height = 200;
avatar.position.set(20, 30);
avatar.scale.set(2, 2);
複製代碼
加載圖片一般須要耗費必定的時間,所以咱們經常使用Loader
來預加載圖片,當圖片所有加載成功後,才渲染出來。
import { Application, Sprite, Loader } from 'pixi.js';
// Loader.shared內置的單例loader
const loader = Loader.shared;
// 也可使用自定義的loader
const loader = new Loader();
const app = new Application({
width: 300,
height: 300,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x1d9ce0
});
document.body.appendChild(app.view);
loader
.add('bili', 'http://pic.deepred5.com/bilibili.jpg')
.add('avatar', 'http://anata.me/img/avatar.jpg')
.load(setup)
// 監聽加載事件
loader.onProgress.add((loader) => {
console.log(loader.progress);
});
function setup() {
const bili = new Sprite(
loader.resources["bili"].texture
);
bili.width = 50;
bili.height = 50;
const avatar = new Sprite(
loader.resources["avatar"].texture
);
avatar.width = 50;
avatar.height = 50;
avatar.position.set(50, 50);
app.stage.addChild(bili);
app.stage.addChild(avatar);
}
複製代碼
經過add
方法添加須要加載的圖片,全部圖片加載完成後,load
方法會調用傳入的setup
回調函數,這時就能夠把圖片精靈加入到app.stage
裏。onProgress
事件能夠監聽加載的進度,經過這個方法,能夠很方便的製做進度條動畫。
前端有時會把多張圖片合併成一張圖片,經過設置background-position
來顯示不一樣的圖片。pixi.js
也有相似的技術,咱們能夠利用Texture Packer軟件,把多張圖片合併成一張圖片,合併的同時,軟件會生成一份json
配置文件,記錄了每張圖片的相對位置。
具體教程見這裏
import { Application, Container, Sprite, Graphics, Loader, Spritesheet } from 'pixi.js';
// myjson記錄了每張圖片的相對位置
import myjosn from './assets/treasureHunter.json';
// mypng裏面有多張圖片
import mypng from './assets/treasureHunter.png';
const loader = Loader.shared;
const app = new Application({
width: 300,
height: 300,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x1d9ce0
});
document.body.appendChild(app.view);
loader
.add('mypng', mypng)
.load(setup)
function setup() {
const texture = loader.resources["mypng"].texture.baseTexture;
const sheet = new Spritesheet(texture, myjosn);
sheet.parse((textures) => {
// mypng裏面的一張叫treasure.png的圖片
const treasure = new Sprite(textures["treasure.png"]);
treasure.position.set(0, 0);
// mypng裏面的一張叫blob.png的圖片
const blob = new Sprite(textures["blob.png"]);
blob.position.set(100, 100);
app.stage.addChild(treasure);
app.stage.addChild(blob);
});
}
複製代碼
Ticker
有點相似前端的requestAnimationFrame
,當瀏覽器的顯示頻率刷新的時候,此函數會被執行,所以經常用來製做動畫。
app.ticker
就是一個Ticker
實例。
import { Application, Sprite, Loader } from 'pixi.js';
const loader = Loader.shared;
const app = new Application({
width: 300,
height: 300,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x1d9ce0
});
document.body.appendChild(app.view);
loader
.add('bili', 'http://pic.deepred5.com/bilibili.jpg')
.load(setup)
function setup() {
const bili = new Sprite(
loader.resources["bili"].texture
);
bili.width = 50;
bili.height = 50;
app.stage.addChild(bili);
app.ticker.add(() => {
if (bili.x <= 200) {
bili.x += 1;
}
})
}
複製代碼
咱們也可使用requestAnimationFrame
實現這個效果
function setup() {
const bili = new Sprite(
loader.resources["bili"].texture
);
bili.width = 50;
bili.height = 50;
app.stage.addChild(bili);
function move() {
if (bili.x <= 200) {
bili.x += 1;
requestAnimationFrame(move)
}
}
requestAnimationFrame(move)
}
複製代碼
Ticker
能夠實現簡單的動畫,但若是咱們但願實現一些複雜效果,則須要本身編寫不少代碼,這時就能夠選擇一個兼容pixi
的動畫庫。市面上比較常見的動畫庫有:Tween.js,TweenMax,這裏咱們使用TweenMax
來演示效果。
安裝動畫庫
npm i gsap
複製代碼
import { Application, Sprite, Loader } from 'pixi.js';
import { TweenMax } from 'gsap/all';
const loader = Loader.shared;
const app = new Application({
width: 300,
height: 300,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x1d9ce0
});
document.body.appendChild(app.view);
loader
.add('bili', 'http://pic.deepred5.com/bilibili.jpg')
.load(setup)
function setup() {
const bili = new Sprite(
loader.resources["bili"].texture
);
bili.width = 50;
bili.height = 50;
app.stage.addChild(bili);
// 1s內x和y軸移動100
TweenMax.to(bili, 1, { x: 100, y: 100 });
}
複製代碼
TweenMax
還提供了一個PixiPlugin,能夠一次修改多個pixi屬性
import { Application, Sprite, Loader } from 'pixi.js';
import * as PIXI from 'pixi.js';
import gsap, { TweenMax, PixiPlugin } from 'gsap/all';
// 註冊插件
gsap.registerPlugin(PixiPlugin);
PixiPlugin.registerPIXI(PIXI);
const loader = Loader.shared;
const app = new Application({
width: 300,
height: 300,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x1d9ce0
});
document.body.appendChild(app.view);
loader
.add('bili', 'http://pic.deepred5.com/bilibili.jpg')
.load(setup)
function setup() {
const bili = new Sprite(
loader.resources["bili"].texture
);
bili.width = 50;
bili.height = 50;
app.stage.addChild(bili);
// 一次修改多個屬性
TweenMax.to(bili, 1, { pixi: { scaleX: 1.2, scaleY: 1.2, skewX: 10, rotation: 20 } });
}
複製代碼
咱們一般使用Pixi提供的Application
方法來建立一個應用,它能自動建立renderer,ticker 和container。但其實,咱們能夠本身來建立這些對象。
import { Container, Renderer, Sprite, Loader, Ticker } from 'pixi.js';
import { TweenMax } from 'gsap/all';
// 自定義render
const renderer = new Renderer({
width: 300,
height: 300,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x1d9ce0
});
// 自定義container
const stage = new Container();
// 自定義loader
const loader = new Loader();
// 自定義ticker
const ticker = new Ticker();
// 每次屏幕刷新從新渲染,不然只會渲染第一幀
ticker.add(() => {
renderer.render(stage);
});
// 開始執行ticker,必定要調用這個方法,註冊的回調函數纔會被執行!!!
ticker.start();
document.body.appendChild(renderer.view);
loader
.add('bili', 'http://pic.deepred5.com/bilibili.jpg')
.load(setup)
function setup() {
const bili = new Sprite(
loader.resources["bili"].texture
);
bili.width = 50;
bili.height = 50;
stage.addChild(bili);
// 動畫效果
ticker.add(() => {
if (bili.x <= 200) {
bili.x += 2;
}
});
TweenMax.to(bili, 1, { y: 100, delay: 3 });
}
複製代碼
其實PIXI.Application的底層就是幫咱們簡化了上述的操做。