PixiJS核心概念及簡單上手
0. PixiJS 介紹
PixiJS是一個輕量級的2D渲染引擎,它能自動偵測使用WebGL還是Canvas來建立圖形。開發者無需專門學習 WebGL 就能感受到強大的硬體加速的力量。
PixiJS 會幫助你用 JavaScript 或者其他 HTML5 技術來顯示媒體,建立動畫或管理互動式影像(精靈),從而製作一個遊戲或應用。它擁有語義化簡潔的 API 介面。比如支援紋理貼圖集和為精靈提供了一些簡單的動畫系統。它也提供了一個完備的場景圖,你可以在精靈圖層裡面建立另一個精靈,當然也可以讓精靈響應你的滑鼠或觸控事件。
要注意的是,雖然 PixiJS 非常適合製作小遊戲,但它並不是一個遊戲引擎,它的核心本質是儘可能快速有效地在螢幕上移動物體。這個庫經常被用來製作HTML5遊戲(微信小遊戲)以及有複雜互動的H5活動頁。
1.搭建環境
注意:本文使用pixi最新的v5版本,同時使用Parcel進行模組化打包pixi.js
v5版本預設使用webgl渲染,如果希望可以回退到canvas,需要使用pixi.js-legacy
,詳情見issue
專案初始化
mkdir learn-pixi
cd learn-pixi
npm init -y
安裝依賴
npm i pixi.js -save
npm i parcel-bundler -save-dev
根目錄建立index.html
<!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
alert('pixi');
修改package.json
"scripts": {
"dev": "parcel index.html -p 8080",
"build": "parcel build index.html"
}
執行npm run dev
,訪問 http://localhost:8080/ 即可看到效果
2.快速開始
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裡
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('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('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;
})
3.基本概念
3.0 Application應用
使用 PixiJS ,我們首先應該建立一個 Pixi 應用,使用 PIXI.Application() 方法可以 new
一個,這個方法可以傳入一個物件引數,這個物件中,可以設定 Pixi 應用的寬、高、是否透明,等一些屬性,具體所有可以設定的屬性可以到 Pixi 的文件裡看。
在使用 PIXI.Application() 方法時,如果你沒有給傳入的引數物件設定 view
屬性,它會自動建立一個canvas
元素,建立出來的 canvas
元素就在 Pixi 應用的 view
屬性中。
pixi
有幾個重要的Class:
- Container (容器)
- **Renderer **(渲染器)
- Sprite (精靈)
- Loader (資源載入器)
- Texture(紋理)
- Ticker (計時器)
const app = new Application({ // 建立一個Pixi 應用
width: 300,
height: 300
});
// 把 Pixi 應用中建立出來的 canvas 新增到頁面上
document.body.appendChild(app.view);
// 在離開頁面時需要手動清理記憶體,否則無法釋放WebGL記憶體
app.destroy(true)
**
3.1 Container 容器
容器是用來裝載多個顯示物件的(類比div), 它可以用 PIXI.Container() 方法來建立,而我們建立的 Pixi 應用的 stage
屬性(類比document.body)就是一個容器物件,它被當作根容器使用,它將包裹所有你想用 Pixi 顯示的東西。
app.stage
是一個Container
的例項,作為最底層的舞臺(stage),所有要渲染的圖形都應放在它的內部。
const app = new Application({
width: 300,
height: 300
});
// 新增不同的圖形, 類似於我們appendChild
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
});
const myContainer = new Container();
// 相對於根節點偏移
myContainer.position.set(40, 40);
const rectangle = new Graphics();
rectangle.beginFill(0x000000);
rectangle.drawRect(0, 0, 64, 64);
rectangle.endFill();
const rectangle2 = new Graphics();
rectangle2.beginFill(0xFFFFFF);
rectangle2.drawRect(0, 0, 64, 64);
rectangle2.endFill();
rectangle2.position.set(20, 20);
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佈局
3.2 Renderer 渲染器
app.renderer
是一個Renderer
的例項,如果你希望重新渲染頁面,就需要使用它, 例如重置畫布大小後,需要重新渲染頁面元素。可以呼叫render方法重新渲染畫布元素。
// CanvasRenderer, WebGLRenderer
const renderer = new PIXI.autoDetectRenderer(256, 256, {
view: document.getElementById('app')
}
);
// 建立 Stage
const stage = new PIXI.Container();
// 用 Render 去渲染 Stage
renderer.render(stage);
// 把畫布重新渲染為500*500大小
app.renderer.resize(500, 500);
// 渲染一個容器
const container = new Container();
app.renderer.render(container);
3.3 Sprite 精靈
Sprite精靈是可以放在容器裡的互動式影像。精靈是你能用程式碼控制影像的基礎。你能夠控制他們的位置,大小,和許多其他有用的屬性來產生互動和動畫。 建立一個精靈需要用 PIXI.Sprite() 方法。
const avatar = new Sprite.from('avatar.jpg');
// 和普通的圖形一樣可以設定各種屬性
avatar.width = 100;
avatar.height = 200;
avatar.position.set(20, 30);
avatar.scale.set(2, 2);
載入圖片通常需要耗費一定的時間,因此我們常常使用Loader
來預載入圖片,當圖片全部載入成功後,才渲染出來。
sprite 具有zIndex屬性,當容器的sortableChildren屬性為true時容器中的所有子元素按照zIndex大小排序。
3.4 Loader 載入器
import { Application, Sprite, Loader } from 'pixi.js';
const loader = Loader.shared;// Loader.shared內建的單例loader
const loader = new Loader();// 也可以使用自定義的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);
});
// 啟動函式setup
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
事件可以監聽載入的進度,通過這個方法,可以很方便的製作進度條動畫。
3.5 Texture 紋理
因為 Pixi 用 WebGL 和 GPU 去渲染影像,所以影像需要轉化成 GPU 可以處理的格式。可以被 GPU 處理的影像被稱作紋理 。在你讓精靈顯示圖片之前,需要將普通的圖片轉化成 WebGL 紋理。為了讓所有工作執行的快速有效率,Pixi使用 紋理快取 來儲存和引用所有你的精靈需要的紋理。紋理的名稱字串就是影像的地址。這意味著如果你有從"cat.png"
載入的影像,你可以在紋理快取PIXI.utils.TextureCache["cat.png"]
中這樣找到它。
前端有時會把多張圖片合併成一張雪碧圖,通過設定background-position
來顯示不同的圖片。pixi.js
也有類似的技術,我們可以利用Texture Packer軟體,把多張圖片合併成一張圖片,合併的同時,軟體會生成一份json
配置檔案,記錄了每張圖片的相對位置,具體教程見這裡
import { Application, Container, Sprite, Graphics, Loader, Spritesheet } from 'pixi.js';
import spriteJson from './assets/treasureHunter.json'; // myjson記錄了每張圖片的相對位置
import imgSprite from './assets/treasureHunter.png';// mypng裡面有多張圖片
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('imgSprite', imgSprite).load(setup)
function setup() {
const texture = loader.resources["imgSprite"].texture.baseTexture;
const sheet = new Spritesheet(texture, spriteJson);
sheet.parse((textures) => {
// imgSprite裡面的一張叫treasure.png的圖片
const treasure = new Sprite(textures["treasure.png"]);
treasure.position.set(0, 0);
// imgSprite裡面的一張叫blob.png的圖片
const blob = new Sprite(textures["blob.png"]);
blob.position.set(100, 100);
app.stage.addChild(treasure);
app.stage.addChild(blob);
});
}
// 銷燬紋理 texture.destroy()
// 重新整理紋理 texture.update()
3.6 Ticker 幀率更新函式
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', '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)
}
3.7 Graphic 幾何圖形
graphics主要用於繪製原始形狀(如線條,圓形和矩形)以及他們的上色和填充。
const graphics = new PIXI.Graphics()
// 線框
graphics.lineStyle(2, 0x0000FF, 1) graphics.drawRect(50, 250, 100, 100)
// 四邊形
graphics.drawRect(50, 50, 100, 100)
// 圓形
graphics.drawCircle(100, 250, 50)
// 橢圓
graphics.drawEllipse(600, 250, 80, 50)
// 圓角矩形
graphics.drawRoundedRect(50, 440, 100, 100, 16)
// 星星
graphics.drawStar(360, 370, 5, 50)
// 多邊形
graphics.drawPolygon(path)
// 貝塞爾曲線
graphics.bezierCurveTo(100, 240, 200, 200, 240, 100)
// 圓弧
graphics.arc(300, 100, 50, Math.PI, 2 * Math.PI)
app.stage.addChild(graphics)
清除圖形 用graphics.clear()方法
text 文字
// 基礎文字
const basicText = new PIXI.Text('6666666')
// 自定義文字樣式
const style = new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 36,
fontStyle: 'italic',
fontWeight: 'bold',
fill: ['#ffffff', '#00ff99'],
stroke: '#4a1850',
strokeThickness: 5,
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6,
wordWrap: true,
wordWrapWidth: 440
})
const richText = new PIXI.Text('6666666', style)
app.stage.addChild(richText)
互動
pixi.js中的事件互動可同時相容移動端和pc端,在繫結事件之前需要開啟互動模式
graphics.interactive = true
在pc端需要出現cursor: pointer
的效果
graphics.buttonMode = true
繫結事件在文件中都有詳細描述(click
, tap
,mousedown
, mousemove
……),下邊簡單寫一下
graphics.on('click', onClick)
function onClick() {
graphics.scale.x *= 1.25
graphics.scale.y *= 1.25
}
- 拖拽功能
const texture = PIXI.Texture.from('examples/assets/bunny.png')
const bunny = new PIXI.Sprite(texture)
bunny
.on('pointerdown', onDragStart)
.on('pointerup', onDragEnd)
.on('pointerupoutside', onDragEnd)
.on('pointermove', onDragMove)
function onDragStart(event) {
this.data = event.data
this.alpha = 0.5
this.dragging = true
}
function onDragEnd() {
this.alpha = 1
this.dragging = false
this.data = null
}
function onDragMove() {
if (this.dragging) {
const newPosition = this.data.getLocalPosition(this.parent)
this.x = newPosition.x
this.y = newPosition.y
}
}
4. 補間動畫
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', '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 } });
}
5. 自定義的Application
我們通常使用Pixi提供的Application
方法來建立一個應用,它能自動建立renderer,ticker 和container。但其實,我們可以自己來建立這些物件。
import { Container, Renderer, Sprite, Loader, Ticker } from 'pixi.js';
import { TweenMax } from 'gsap/all';
const renderer = new Renderer({ // 自定義render
width: 300,
height: 300,
antialias: true,
transparent: false,
resolution: 1,
backgroundColor: 0x1d9ce0
});
const stage = new Container();// 自定義container
const loader = new Loader();
const ticker = new Ticker();
// 每次螢幕重新整理重新渲染,否則只會渲染第一幀
ticker.add(() => {
renderer.render(stage);
});
ticker.start(); // 開始執行ticker,一定要呼叫這個方法,註冊的回撥函式才會被執行!!!
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的底層就是幫我們簡化了上述的操作。
6. 感受一下
下面這些是用 PixiJS 實現的一些例子,你可以點開看看。
cavalier challenge
Run Pixie Run
Filters Demo
WASTE INVADERS
Storm Brewing
H5場景小動畫
打磚塊遊戲
參考
主要參考:https://juejin.im/post/6844904020939636744
相關文章
- MongoDB 簡單上手MongoDB
- spring之AOP的概念及簡單案例Spring
- Airtest簡單上手講解AI
- PixiJS 專案例項以及繪製流程的簡單介紹JS
- FusionServer uMate 簡單上手指南Server
- Kubernetes概念及核心物件物件
- Flutter狀態管理Provider,簡單上手FlutterIDE
- vuex 中的核心概念及原理Vue
- 快速上手python的簡單web框架flaskPythonWeb框架Flask
- Docker Swarm 核心概念及詳細使用DockerSwarm
- DotNetty關鍵概念及簡單示例(基於NET5)Netty
- 快速上手Linux核心命令Linux
- PixiJS原始碼分析系列: 第一章 從最簡單的例子入手JS原始碼
- phpspider簡單快速上手的php爬蟲框架PHPIDE爬蟲框架
- 簡單上手SpringBean的整個裝配過程SpringBean
- 瀏覽器核心-流程概況瀏覽器
- Maven筆記之核心概念及常用命令Maven筆記
- 區塊鏈核心技術概覽區塊鏈
- Linux4.1.15核心啟動流程簡單分析Linux
- 完整版通訊錄(實現簡單具體易上手!!)
- 一款簡單易上手的操作的影片編輯SDK
- 直播app系統原始碼,簡單易上手的進度條APP原始碼
- GitHub Contribution 貢獻圖手辦 | 簡單上手 | 技術點評Github
- 學習 PixiJS — 粒子效果JS
- 開始學習 PixiJSJS
- RecBole小白入門系列部落格(一)——快速安裝和簡單上手
- zookeeper核心之ZAB協議就這麼簡單!協議
- openGauss核心分析2:簡單查詢的執行
- KubeVela 1.4:讓應用交付更安全、上手更簡單、過程更透明
- Linux核心實戰(二)- 作業系統概覽Linux作業系統
- 核心簡介
- 學習 PixiJS — 碰撞檢測JS
- 學習 PixiJS — 視覺效果JS視覺
- 學習 PixiJS — 互動工具JS
- 快速上手Linux核心命令(八):網路相關命令Linux
- 簡單總結nodejs處理tcp連線的核心流程NodeJSTCP
- 學習 PixiJS — 動畫精靈JS動畫
- 學習 PixiJS — 精靈狀態JS