學習 PixiJS — 動畫精靈

FEWY發表於2019-01-14

說明

看完官方教程中提到的這本書 — Learn Pixi.js ,準備寫寫讀後感了,官方教程中所說的內容,基本上就是書的前4章,所以我就從第5章開始寫寫吧。

動畫精靈指的是按順序使用一系列略有不同的影象,建立的精靈,之後一幀一幀的播放這些影象,就可以產生運動的幻覺。

也就是說用這種圖片

在這裡插入圖片描述

做出這樣的效果

在這裡插入圖片描述

要製作動畫精靈我們需要用到 PixiJSAnimatedSprite 方法。

PIXI.extras.AnimatedSprite

定義:

使用紋理陣列建立動畫精靈的方法。

用法:

new PIXI.extras.AnimatedSprite(textures,autoUpdate)
複製程式碼

引數 :

名稱 型別 預設值 描述
textures array 用一系列略有不同的影象做的紋理陣列。
autoUpdate boolean true 用來判斷是否使用 PIXI.ticker.shared 自動更新動畫時間。

返回值:
返回一個物件,物件會有一些屬性和方法,用於控制動畫精靈。

返回值物件的屬性:

名稱 型別 描述
animationSpeed number 動畫精靈的播放速度。越高越快,越低越慢,預設值是1
currentFrame number(只讀) 正在顯示的當前幀編號
onComplete function loop屬性為false時,一個動畫精靈完成播放時呼叫
playing Boolean 確定當前動畫精靈是否正在播放
onFrameChange function 當一個動畫精靈更改要呈現的紋理時呼叫
loop boolean 動畫精靈是否在播放後重復播放
onLoop function loop屬性為true時呼叫的函式
textures array 用於這個動畫精靈的紋理陣列
totalFrames number (只讀) 動畫中的幀總數

返回值物件的方法:

名稱 引數 描述
play 播放動畫精靈
gotoAndPlay frameNumber,number型別,開始幀的索引 轉到特定的幀並開始播放動畫精靈
stop 停止播放動畫精靈
gotoAndStop frameNumber,number型別,停止幀的索引 轉到特定的幀並停止播放動畫精靈

使用返回值中的這些屬性和方法,我們就可以控制動畫精靈了,比如播放動畫精靈,設定動畫的速度,設定是否迴圈播放等,除此之外,還要知道就是 PIXI.extras.AnimatedSprite 方法繼承自 PIXI.Sprite 方法,所以動畫精靈也可以用普通精靈的屬性和方法,比如xywidthheightscalerotation

好的,我們開始試試這個方法。

<!doctype html>
<html lang="zn">

<head>
    <meta charset="UTF-8">
    <title>動畫精靈</title>
</head>

<body>
    <div id="px-render"></div>

    <script src="https://www.kkkk1000.com/js/pixi4.8.2.js"></script>
    <script>
        // 建立一個 Pixi應用 需要的一些引數
        let option = {
            width: 400,
            height: 300,
            transparent: true,
        }
        // 建立一個 Pixi應用
        let app = new PIXI.Application(option);
        // 獲取渲染器
        let renderer = app.renderer;
        let playground = document.getElementById('px-render');
        // 把 Pixi 建立的 canvas 新增到頁面上
        playground.appendChild(renderer.view);

        //設定別名
        let TextureCache = PIXI.utils.TextureCache;
        let Texture = PIXI.Texture;
        let Rectangle = PIXI.Rectangle;
        let AnimatedSprite = PIXI.extras.AnimatedSprite;

        //需要載入的雪碧圖的地址(該圖片伺服器端已做跨域處理)
        let imgURL = "https://user-gold-cdn.xitu.io/2019/1/14/16849ce12c0e953a?w=320&h=286&f=png&s=27286";

        //載入影象,載入完成後執行setup函式 
        PIXI.loader.add(imgURL).load(setup);

        function setup() {
            //獲取紋理
            let base = TextureCache[imgURL];

            //第一個紋理
            let texture0 = new Texture(base);
            texture0.frame = new Rectangle(0, 0, 80, 143);
            //第二個紋理
            let texture1 = new Texture(base);
            texture1.frame = new Rectangle(80, 0, 80, 143);
            //第三個紋理
            let texture2 = new Texture(base);
            texture2.frame = new Rectangle(160, 0, 80, 143);
            //第四個紋理
            let texture3 = new Texture(base);
            texture3.frame = new Rectangle(240, 0, 80, 143);

            //建立紋理陣列
            let textures = [texture0, texture1, texture2, texture3];
            //建立動畫精靈
            let pixie = new PIXI.extras.AnimatedSprite(textures);
            //設定動畫精靈的速度
            pixie.animationSpeed = 0.1;

            //把動畫精靈新增到舞臺
            app.stage.addChild(pixie);
            //播放動畫精靈
            pixie.play();
        }
    </script>
</body>

</html>
複製程式碼

檢視效果

上面這個例子中,建立紋理陣列時似乎點麻煩,要解決這個問題,我們可以用名叫 SpriteUtilities 的庫,該庫包含許多有用的函式,用於建立Pixi精靈並使它們更易於使用。

安裝:

直接用 script 標籤,引入js 檔案就可以

<script src="https://www.kkkk1000.com/js/spriteUtilities.js"></script>
複製程式碼

安裝好之後,我們需要建立一個新例項,程式碼如下

let su = new SpriteUtilities(PIXI);
複製程式碼

之後就可以用 su 物件訪問所有方法了。

我們這裡需要用到的就是 su 物件的 filmstrip 方法。

定義:

filmstrip 方法可以自動將雪碧圖轉換為可用於製作精靈的紋理陣列

用法:

su.filmstrip("anyTilesetImage.png", frameWidth, frameHeight, optionalPadding);
複製程式碼

引數:

名稱 型別 描述
anyTilesetImage string 雪碧圖的路徑
frameWidth number 每幀的寬度(以畫素為單位)
frameHeight number 每幀的高度(以畫素為單位)
optionalPadding number 每幀周圍的填充量(可選值,以畫素為單位)

返回值:

返回一個陣列,可用於製作動畫精靈的紋理陣列。

現在我們使用 SpriteUtilities 來改寫下剛才的示例程式碼。

<!doctype html>
<html lang="zn">

<head>
    <meta charset="UTF-8">
    <title>動畫精靈</title>
</head>

<body>
    <div id="px-render"></div>

    <script src="https://www.kkkk1000.com/js/pixi4.8.2.js"></script>
    <script src="https://www.kkkk1000.com/js/spriteUtilities.js"></script>
    <script>
        //建立一個 Pixi應用 需要的一些引數
        let option = {
            width: 400,
            height: 300,
            transparent: true,
        }
        //建立一個 Pixi應用
        let app = new PIXI.Application(option);
        //獲取渲染器
        let renderer = app.renderer;
        let playground = document.getElementById('px-render');
        //把 Pixi 建立的 canvas 新增到頁面上
        playground.appendChild(renderer.view);

        let su = new SpriteUtilities(PIXI);
        //需要載入的雪碧圖的地址(該圖片伺服器端已做跨域處理)
        let imgURL = "https://user-gold-cdn.xitu.io/2019/1/14/16849ce12c0e953a?w=320&h=286&f=png&s=27286";
        PIXI.loader.add(imgURL).load(setup);

        function setup() {
            //建立紋理陣列
            let frames = su.filmstrip(imgURL, 80, 143);
            //建立動畫精靈
            let pixie = new PIXI.extras.AnimatedSprite(frames);
            //設定動畫精靈的速度
            pixie.animationSpeed = 0.1;

            //把動畫精靈新增到舞臺
            app.stage.addChild(pixie);
            //播放動畫精靈
            pixie.play();
        }
    </script>
</body>

</html>
複製程式碼

檢視效果

filmstrip 方法自動將整個雪碧圖轉換為可用於製作動畫精靈的紋理陣列。但是,如果我們只想使用雪碧圖中的一部分幀呢?這時候需要用到 frames 方法了。

定義:

frames 方法使用雪碧圖中的一組子幀,來建立紋理陣列。

用法:

su.frames(source, coordinates, frameWidth, frameHeight)
複製程式碼

引數:

名稱 型別 描述
source string 雪碧圖的路徑
coordinates array 包含每幀的 x 和 y 座標的二維陣列
frameWidth number 每幀的寬度(以畫素為單位)
frameHeight number 每幀和高度(以畫素為單位)

返回值:
返回一個陣列,可用於製作動畫精靈的紋理陣列。

示例程式碼:

<!doctype html>
<html lang="zn">

<head>
    <meta charset="UTF-8">
    <title>動畫精靈</title>
</head>

<body>
    <div id="px-render"></div>

    <script src="https://www.kkkk1000.com/js/pixi4.8.2.js"></script>
    <script src="https://www.kkkk1000.com/js/spriteUtilities.js"></script>
    <script>
        //建立一個 Pixi應用 需要的一些引數
        let option = {
            width: 400,
            height: 300,
            transparent: true,
        }
        //建立一個 Pixi應用
        let app = new PIXI.Application(option);
        //獲取渲染器
        let renderer = app.renderer;
        let playground = document.getElementById('px-render');
        //把 Pixi 建立的 canvas 新增到頁面上
        playground.appendChild(renderer.view);

        let su = new SpriteUtilities(PIXI);
        //需要載入的雪碧圖的地址(該圖片伺服器端已做跨域處理)
        let imgURL = "https://user-gold-cdn.xitu.io/2019/1/14/16849ce12c0e953a?w=320&h=286&f=png&s=27286";

        PIXI.loader.add(imgURL).load(setup);
        function setup() {
            //建立紋理陣列
            let frames = su.frames(imgURL, [[0, 0], [80, 0], [160, 0], [240, 0]], 80, 143);
            //建立動畫精靈
            let pixie = new PIXI.extras.AnimatedSprite(frames);
            //設定動畫精靈的速度
            pixie.animationSpeed = 0.1;

            //把動畫精靈新增到舞臺
            app.stage.addChild(pixie);
            //播放動畫精靈
            pixie.play();
        }
    </script>
</body>

</html>
複製程式碼

檢視效果

除了上面提到的方式,還可以用紋理貼圖集來建立動畫精靈。

使用紋理貼圖集來建立動畫精靈,就是先通過json檔案,載入所有紋理,然後把需要的紋理再放進一個陣列中,最後把這個陣列當引數,傳入PIXI.extras.AnimatedSprite 方法中,來建立動畫精靈。

程式碼:

<!doctype html>
<html lang="zn">

<head>
    <meta charset="UTF-8">
    <title>動畫精靈</title>
</head>

<body>
    <div id="px-render"></div>

    <script src="https://www.kkkk1000.com/js/pixi4.8.2.js"></script>
    <script>
        //建立一個 Pixi應用 需要的一些引數
        let option = {
            width: 400,
            height: 300,
            transparent: true,
        }
        //建立一個 Pixi應用
        let app = new PIXI.Application(option);
        //獲取渲染器
        let renderer = app.renderer;
        let playground = document.getElementById('px-render');
        //把 Pixi 建立的 canvas 新增到頁面上
        playground.appendChild(renderer.view);

        //需要載入的紋理貼圖集的地址
        let textureURL = "https://www.kkkk1000.com/images/learnPixiJS-AnimatedSprite/dnf.json";

        //載入紋理貼圖集,載入完成後執行setup函式
        PIXI.loader.add(textureURL).load(setup);

        function setup() {
            let id = PIXI.loader.resources[textureURL].textures;

            //建立紋理陣列
            let frames = [
                id["dnf0.png"],
                id["dnf1.png"],
                id["dnf2.png"],
                id["dnf3.png"]
            ];
            //建立動畫精靈
            let pixie = new PIXI.extras.AnimatedSprite(frames);
            //設定動畫精靈的速度
            pixie.animationSpeed = 0.1;

            //把動畫精靈新增到舞臺
            app.stage.addChild(pixie);
            //播放動畫精靈
            pixie.play();
        }
    </script>
</body>

</html>
複製程式碼

檢視效果

上面的程式碼建立紋理陣列時,是把紋理一個一個的放進陣列中,如果數量比較少還好,多一點呢?假如有100個呢?一個一個的放就太麻煩了,這時候我們可以用 SpriteUtilities 庫中提供的 frameSeries 方法。

定義:

frameSeries 方法可以通過已載入的紋理貼圖集,使用一系列編號的幀ID來建立動畫精靈。

用法:

su.frameSeries(startNumber, endNumber, baseName, extension)
複製程式碼

引數:

名稱 型別 描述
startNumber number 起始幀序列號(預設值是0)
endNumber number 結束幀序列號(預設值是1)
baseName string 可選的基本檔名
extension string 可選的副檔名

返回值:
返回一個陣列,可用於製作動畫精靈的紋理陣列。

注意:
使用 frameSeries 方法時,要確保在 json 檔案中,定義的每幀的名稱都是按順序來的,比如 frame0.png frame1.png frame2.png 這種。因為 frameSeries 方法的原始碼是這樣寫的

 frameSeries(startNumber = 0, endNumber = 1, baseName = "", extension = "") {
   //建立一個陣列來儲存幀名
   let frames = [];

   for (let i = startNumber; i < endNumber + 1; i++) {
     let frame = this.TextureCache[`${baseName + i + extension}`];
     frames.push(frame);
   }
   return frames;
 }
複製程式碼

原始碼中其實是用 for 迴圈把幀名拼接起來的。所以要保證幀名是按順序來的,不然就獲取不到了。

下來我們就試試 frameSeries 方法吧。

<!doctype html>
<html lang="zn">

<head>
    <meta charset="UTF-8">
    <title>動畫精靈</title>
</head>

<body>
    <div id="px-render"></div>

    <script src="https://www.kkkk1000.com/js/pixi4.8.2.js"></script>
    <script src="https://www.kkkk1000.com/js/spriteUtilities.js"></script>
    <script>
        //建立一個 Pixi應用 需要的一些引數
        let option = {
            width: 400,
            height: 300,
            transparent: true,
        }
        //建立一個 Pixi應用
        let app = new PIXI.Application(option);
        //獲取渲染器
        let renderer = app.renderer;
        let playground = document.getElementById('px-render');
        //把 Pixi 建立的 canvas 新增到頁面上
        playground.appendChild(renderer.view);

        let su = new SpriteUtilities(PIXI);
        //需要載入的紋理貼圖集的地址
        let textureURL = "https://www.kkkk1000.com/images/learnPixiJS-AnimatedSprite/dnf.json";

        PIXI.loader.add(textureURL).load(setup);
        function setup() {
            //建立紋理陣列
            debugger;
            let frames = su.frameSeries(0, 7, "dnf", ".png");
            //建立動畫精靈
            let pixie = new PIXI.extras.AnimatedSprite(frames);
            //設定動畫精靈的速度
            pixie.animationSpeed = 0.1;

            //把動畫精靈新增到舞臺
            app.stage.addChild(pixie);
            //播放動畫精靈
            pixie.play();
        }
    </script>
</body>

</html>
複製程式碼

檢視效果

注意版本問題:
1、PIXI.extras.AnimatedSprite 這個方法原來叫PIXI.extras.MovieClip ,是在 4.2.1 版本的時候修改的,本文示例程式碼中用 PixiJS 的版本是 4.8.2,所以沒有問題,如果你在使用過程中發現呼叫PIXI.extras.AnimatedSprite 這個方法有問題,可以先檢查下版本是否正確。

2、 SpriteUtilities 目前支援的 PixiJS 的版本是 3.0.11,而 SpriteUtilities 中用的就是PIXI.extras.MovieClip 方法,所以你如果用了比較高的 PixiJS 的版本,需要在SpriteUtilities 中修改下方法的別名。

spriteUtilities.js 檔案中需要把 renderingEngine.extras.MovieClip 改成renderingEngine.extras.AnimatedSprite,把 renderingEngine.ParticleContainer 改成 PIXI.particles.ParticleContainer

這個 spriteUtilities.js 就是修改後的。

當然你也可以使用低版本的 PixiJS,這樣就不用改 spriteUtilities.js 的程式碼了。

總結

動畫精靈就是逐幀動畫,通過一幀一幀的播放影象來產生運動的幻覺。

本文就是聊了聊建立動畫精靈的一些方式和如何使用動畫精靈。

如果文中有錯誤的地方,還請小夥伴們指出,萬分感謝。

下一篇 學習 PixiJS — 精靈狀態

相關文章