說明
補間動畫指的是,我們可以通過為精靈的位置、比例、透明度,等屬性,設定開始值和結束值,製作動畫,動畫中間需要的部分由軟體自動計算填充。
Pixi 沒有內建補間引擎,但是你可以使用很多很好的開源的補間庫,比如 Tween.js 和 Dynamic.js 。如果要製作非常專業的自定義補間效果,可以使用這兩個庫中的其中一個。但是現在我們要使用的是一個名為 Charm.js 的專門用於 Pixi 的補間庫。
使用 Charm 庫
要開始使用 Charm ,首先直接用 script 標籤,引入 js 檔案
<script src="https://www.kkkk1000.com/js/Charm.js"></script>
複製程式碼
然後建立它的例項
let c = new Charm(PIXI);
複製程式碼
變數 c
現在代表 Charm 例項。
和前面的文章中講到的粒子效果一樣,在呼叫 state 函式之後,必須為遊戲迴圈中的每個幀更新補間。就是在遊戲迴圈中呼叫 Charm 的 update 方法,如下所示:
function gameLoop() {
requestAnimationFrame(gameLoop);
state();
c.update();
renderer.render(stage);
}
複製程式碼
滑動補間
Charm 最有用的補間效果之一是 slide 。使用 slide 方法可以使精靈從畫布上的當前位置平滑移動到任何其他位置。slide 方法有七個引數,但只有前三個引數是必需的。
名稱 | 預設值 | 描述 |
---|---|---|
anySprite | 需要移動的精靈 | |
finalXPosition | 滑動結束時 x 座標 | |
finalYPosition | 滑動結束時 y 座標 | |
durationInFrames | 60 | 補間需要的幀數,也就是動畫應該持續多長時間 |
easingType | "smoothstep" |
緩動型別 |
yoyo | false | 用於確定精靈是否應在補間的起點和終點之間來回移動。 |
delayTimeBeforeRepeat | 0 | 一個以毫秒為單位的數字,用於確定精靈 yoyo 之前的延遲時間。 |
示例:
以下是如何使用 slide 方法使精靈用120幀從原始位置移動到座標為(128,128)的位置的關鍵程式碼。
c.slide(sprite, 128, 128, 120);
複製程式碼
效果圖:
檢視示例如果你想讓精靈在起點和終點之間來回移動,請將 yoyo
(第六個引數)設定為 true,程式碼如下所示:
c.slide(sprite, 128, 128, 120, "smoothstep", true);
複製程式碼
補間物件
Charm 所有的補間方法都返回一個補間物件,你可以這樣建立:
let slidePixie = c.slide(sprite, 80, 128, 120, "smoothstep",true);
複製程式碼
slidePixie 就是補間物件,它包含一些有用的屬性和方法,可以用於控制補間。
其中一個是 onComplete 方法,它將在補間完成後立即執行。以下程式碼是精靈到達終點時如何使用 onComplete 方法在控制檯中顯示訊息。
let slidePixie = c.slide(sprite, 80, 128, 120, "smoothstep",true);
slidePixie.onComplete = () => console.log("一次滑動完成");
複製程式碼
如果將 yoyo
(slide 方法的第六個引數)設定為 true,則每當精靈到達其起點和終點時,onComplete 方法都將執行。
補間還有 pause 和 play 方法,可以停止和開始補間。
slidePixie.pause();
slidePixie.play();
複製程式碼
補間物件還具有 playing 屬性,如果補間當前正在播放,則該屬性值為 true。只不過有些補間方法返回的物件中直接有 playing 屬性,有些補間方法返回的物件中的 playing 屬性是在一個叫 tweens 的陣列中, tweens 陣列中包括了這個補間方法建立的所有補間物件。 以 slide 方法為例,完成一個滑動需要建立 x 軸補間物件和 y 軸補間物件,這兩個物件都放在了 tweens 陣列中,這兩個物件也都分別有 playing 屬性。
所有 Charm 的補間方法都返回你可以控制和訪問的補間物件。
設定緩動型別
slide 方法的第四個引數是 easingType 。它是一個字串,用於確定補間加速和減速的型別。這些型別共有15種可供選擇,並且它們對於 Charm 的所有不同補間方法都是相同的。某些型別對應的會有一個基本型別,一個 squared 型別和一個cubed 型別。squared 型別和 cubed 型別只是將基本型別的效果放大而已。大多數 Charm 的補間效果的預設緩動型別是 smoothstep。
Linear:
linear
,精靈從開始到停止保持勻速運動。
Smoothstep:
smoothstep
,smoothstepSquared
,smoothstepCubed
。加速精靈並以非常自然的方式減慢速度
Acceleration:
acceleration
, accelerationCubed
。逐漸加速精靈並突然停止。
如果要更加平滑的加速效果,請使用 sine
,sineSquared
或 sineCubed
。
Deceleration:
deceleration
,decelerationCubed
。突然加速精靈並逐漸減慢它。要獲得更加平滑的減速效果,請使用inverseSine
,inverseSineSquared
或inverseSineCubed
。
Bounce:
bounce 10 -10
,這將使精靈到達起點和終點時略微反彈,更改乘數10和 -10,可以改變效果。
使用 slide 進行場景過渡
你在遊戲或應用程式中肯定要做的一件事就是讓場景過渡,然後將新場景滑入檢視。它可能是你遊戲的標題滑動以顯示遊戲的第一級,或者可能是一個選單,可以滑動以顯示更多的應用程式內容。你可以使用 slide
方法執行此操作。
首先,建立兩個容器物件:sceneOne
和 sceneTwo
,並將它們新增到舞臺上。
sceneOne = new Container();
sceneTwo = new Container();
stage.addChild(sceneOne);
stage.addChild(sceneTwo);
複製程式碼
接下來,為每個場景建立精靈。製作一個像畫布一樣大的藍色矩形; 並在矩形中間新增上 Scene One
的文字,將兩者都新增到 sceneOne
容器中。再製作一個像畫布一樣大的紅色矩形;並在矩形中間新增上Scene Two
的文字,將這兩者新增到 sceneTwo
容器中。你最終得到的兩個容器物件,如下圖所示。
以下是關鍵程式碼:
//1. Scene one sprites:
//畫藍色矩形
let blueRectangle = new PIXI.Graphics();
blueRectangle.beginFill(0x014ACA);
blueRectangle.drawRect(0, 0, canvasWith, canvasHeight);
blueRectangle.endFill();
sceneOne.addChild(blueRectangle);
//新增文字,並在容器中居中
let sceneOneText = new PIXI.Text("Scene One");
sceneOneText.style = { fill: "#fff", fontSize: "40px" };
let sceneOneTextX = (canvasWith - sceneOneText.width) / 2;
let sceneOneTextY = (canvasWith - sceneOneText.height) / 2;
sceneOneText.position.set(sceneOneTextX, sceneOneTextY);
sceneOne.addChild(sceneOneText);
//2. Scene two sprites:
//畫紅色矩形
let redRectangle = new PIXI.Graphics();
redRectangle.beginFill(0xEF4631);
redRectangle.drawRect(0, 0, canvasWith, canvasHeight);
redRectangle.endFill();
sceneTwo.addChild(redRectangle);
//新增文字,並在容器中居中
let sceneTwoText = new PIXI.Text("Scene Two");
sceneTwoText.style = { fill: "#fff", fontSize: "40px" };
let sceneTwoTextX = (canvasWith - sceneTwoText.width) / 2;
let sceneTwoTextY = (canvasHeight - sceneTwoText.height) / 2;
sceneTwoText.position.set(sceneTwoTextX, sceneTwoTextY);
sceneTwo.addChild(sceneTwoText);
複製程式碼
在一個真實的專案中,你可以為每個容器填充每個場景所需的精靈數量,你也可以為你的專案新增儘可能多的場景容器。
接下來,將 sceneTwo
移開,使其位於畫布的右邊緣之外。程式碼如下所示:
sceneTwo.x = canvasWith;
複製程式碼
這將在畫布上顯示 sceneOne
,而 sceneTwo
在需要時會從左側滑出,如下所示。
sceneTwo
就在螢幕外等著。
最後,使用 slide
方法從 sceneOne
過渡到 sceneTwo
。只需將 sceneOne
滑動到左側,然後從右側滑動 sceneTwo
,取代它的位置,程式碼如下。
c.slide(sceneTwo, 0, 0);
c.slide(sceneOne, -canvasWith, 0);
複製程式碼
下圖顯示了這段程式碼的效果。
時間過渡
你可以自定義一個 wait
函式在設定的時間間隔後進行過渡。
function wait(duration = 0) {
return new Promise((resolve, reject) => {
setTimeout(resolve, duration);
});
}
複製程式碼
要使用 wait
,請為其提供一個引數,它代表你希望等待的時間(以毫秒為單位)。以下是在延遲1秒(1000毫秒)後從 sceneOne
過渡到 sceneTwo
的方法。
wait(1000).then(() => {
c.slide(sceneTwo, 0, 0);
c.slide(sceneOne, -canvasWith, 0);
});
複製程式碼
其實在 Charm 庫中已經定義了 wait 這個方法,原理和上面的 wait 函式是一樣的。你可以這樣使用它。
c.wait(1000).then(() => {
c.slide(sceneTwo, 0, 0);
c.slide(sceneOne, -canvasWith, 0);
});
複製程式碼
沿貝塞爾曲線移動
slide 方法沿直線為精靈製作動畫,但你也可以使用另一種方法(followCurve)使精靈沿貝塞爾曲線移動。首先,將貝塞爾曲線定義為4個座標點的二維陣列,如下所示:
let curve = [
[sprite.x, sprite.y], //起始點
[108, 32], //控制點1
[176, 32], //控制點2
[196, 160] //結束點
];
複製程式碼
followCurve 方法的引數如下:
名稱 | 預設值 | 描述 |
---|---|---|
anySprite | 需要移動的精靈 | |
curve | 貝塞爾曲線陣列 | |
durationInFrames | 60 | 補間需要的幀數,也就是動畫應該持續多長時間 |
easingType | "smoothstep" |
緩動型別 |
yoyo | false | 用於確定精靈是否應在補間的起點和終點之間來回移動。 |
delayTimeBeforeRepeat | 0 | 一個以毫秒為單位的數字,用於確定精靈 yoyo 之前的延遲時間。 |
接下來,使用 Charm 的 followCurve
方法使精靈跟隨該曲線。(提供 curve 陣列作為第二個引數)
c.followCurve(
sprite, //需要移動的精靈
curve, //貝塞爾曲線陣列
120, //持續時間,以幀為單位
"smoothstep", //緩動型別
true, //yoyo
1000 //yoyo之前的延遲時間
);
複製程式碼
效果圖:
如果你需要使精靈的中點沿著曲線移動,還需要設定精靈的錨點(anchor)居中,如下所示:
sprite.anchor.set(0.5, 0.5);
複製程式碼
slide
和 followCurve
方法適用於簡單的來回動畫效果,但你也可以結合它們以使精靈遵循更復雜的路徑。
沿路徑移動
你可以使用 Charm 的 walkPath
方法連線一系列點,並使精靈移動到每個點。該系列中的每個點都稱為 waypoint
。首先,從由座標點組成的二維陣列定位路徑點開始,這些 waypoint
對映出你希望精靈遵循的路徑。
let waypoints = [
[32, 32], //要移動到的第一個座標點
[32, 128], //要移動到的第二個座標點
[300, 128], //要移動到的第三個座標點
[300, 32], //要移動到的第四個座標點
[32, 32] //要移動到的第五個座標點
];
複製程式碼
你可以根據需要使用任意多的 waypoint
。
walkPath 方法的引數如下:
名稱 | 預設值 | 描述 |
---|---|---|
anySprite | 需要移動的精靈 | |
waypoints | 座標點的二維陣列 | |
durationInFrames | 60 | 補間需要的幀數,也就是動畫應該持續多長時間 |
easingType | "smoothstep" |
緩動型別 |
loop | false | 用於確定精靈在到達結尾時是否從頭開始 |
yoyo | false | 用於確定精靈是否應在補間的起點和終點之間來回移動。 |
delayBetweenSections | 0 | 一個以毫秒為單位的數字,用於確定精靈在移動到路徑的下一部分之前應該等待的時間。 |
接下來,使用 walkPath
方法使精靈按順序移動到所有這些點。(前兩個引數是必需的)
c.walkPath(
sprite, //需要移動的精靈
waypoints, //座標點的二維陣列
300, //持續時間,以幀為單位
"smoothstep", //緩動型別
true, //迴圈
true, //輪流反向播放動畫
1000 //移動到路徑的下一部分之前應該等待的時間
);
複製程式碼
效果圖:
而使用 walkCurve
方法,可以使精靈遵循一系列連線的貝塞爾曲線。首先,建立任何貝塞爾曲線陣列,描述你希望精靈遵循的路徑。
let curvedWaypoints = [
//第一條曲線
[[sprite.x, sprite.y],[75, 500],[200, 500],[300, 300]],
//第二條曲線
[[300, 300],[250, 100],[100, 100],[sprite.x, sprite.y]]
];
複製程式碼
每條曲線的四個點與 followCurve
方法中的相同:起始位置,控制點1,控制點2和結束位置。第一條曲線中的最後一個點應與下一條曲線中的第一個點相同。你可以根據需要使用盡可能多的曲線。
walkCurve 方法的引數如下:
名稱 | 預設值 | 描述 |
---|---|---|
anySprite | 需要移動的精靈 | |
curvedWaypoints | 貝塞爾曲線的座標點的陣列 | |
durationInFrames | 60 | 補間需要的幀數,也就是動畫應該持續多長時間 |
easingType | "smoothstep" |
緩動型別 |
yoyo | false | 用於確定精靈是否應在補間的起點和終點之間來回移動。 |
delayBeforeContinue | 0 | 一個以毫秒為單位的數字,用於確定精靈yoyo 之前的延遲時間。 |
接下來,提供 curvedWaypoints
陣列作為 walkCurve
方法中的第二個引數,來試試這個方法。
c.walkCurve(
sprite, //需要移動的精靈
curvedWaypoints, //貝塞爾曲線的座標點的陣列
300, //持續時間,以幀為單位
"smoothstep", //緩動型別
true, //迴圈
true, //輪流反向播放動畫
1000 //移動到路徑的下一部分之前應該等待的時間
);
複製程式碼
效果圖:
使用 walkPath 和 walkCurve 將為你提供了一個很好的開端,它們可以為遊戲製作一些有趣的動畫。
更多補間效果
Charm 有許多其他內建的補間效果,你會發現它們在遊戲和應用程式中有很多用處。下面是其他一些效果的介紹。
fadeOut 和 fadeIn fadeOut 方法使精靈逐漸變得透明,fadeIn 方法使精靈從透明逐漸顯現。這兩個方法需要的引數是一樣的。
引數:
名稱 | 預設值 | 描述 |
---|---|---|
anySprite | 需要產生效果的精靈 | |
durationInFrames | 60 | 持續的幀數 |
示例:
c.fadeOut(anySprite);
c.fadeIn(anySprite);
複製程式碼
pulse
使用 pulse 方法可以使精靈以穩定的速率連續淡入淡出。
引數:
名稱 | 預設值 | 描述 |
---|---|---|
anySprite | 需要產生效果的精靈 | |
durationInFrames | 60 | 淡入淡出應該持續的幀數,也就是持續時間 |
minAlpha | 0 | 精靈可以減少到的最小的透明度值 |
示例:
c.pulse(anySprite);
複製程式碼
如果你只希望精靈在再次淡入之前變為半透明,請將第三個引數設定為0.5,如下所示:
c.pulse(anySprite, 60, 0.5);
複製程式碼
scale
你可以使用 scale 方法讓精靈產生縮放效果。
引數:
名稱 | 預設值 | 描述 |
---|---|---|
anySprite | 需要產生效果的精靈 | |
endScaleX | 0.5 | x 軸縮放的比例 |
endScaleY | 0.5 | y 軸縮放的比例 |
durationInFrames | 60 | 持續時間,以幀為單位 |
示例:
c.scale(
sprite, //精靈
0.1, //x軸縮放的比例
0.1, //y軸縮放的比例
100 //持續時間,以幀為單位
);
複製程式碼
breathe
如果你希望縮放效果來回 yoyo
,請使用 breathe 方法。它是一種縮放效果,使精靈看起來好像在呼吸。
引數:
名稱 | 預設值 | 描述 |
---|---|---|
anySprite | 需要產生效果的精靈 | |
endScaleX | 0.5 | x 軸縮放的比例 |
endScaleY | 0.5 | y 軸縮放的比例 |
durationInFrames | 60 | 持續時間,以幀為單位 |
yoyo | true | 是否輪流反向播放 |
delayBeforeRepeat | 0 | 一個以毫秒為單位的數字,用於確定精靈 yoyo 之前的延遲時間。 |
示例:
c.breathe(
sprite, //精靈
0.1, //x軸縮放的比例
0.1, //y軸縮放的比例
100, //持續時間,以幀為單位
true, //輪流反向播放
0, //yoyo 之間的延遲時間
);
複製程式碼
strobe
使用 strobe 方法通過快速改變精靈比例,使精靈看起來像閃光燈一樣閃爍。
引數: 只需要傳入一個精靈作為引數即可。
示例:
c.strobe(sprite);
複製程式碼
wobble
使用 wobble 方法可以使精靈像果凍一樣擺動。
引數: 只需要傳入一個精靈作為引數即可。
示例:
c.wobble(sprite);
複製程式碼
如果你使用這些縮放補間效果(scale,breathe,strobe,或者 wobble),將精靈的錨點居中,就可以從精靈的中心進行縮放。
sprite.anchor.set(0.5, 0.5);
複製程式碼
注意:
目前, Charm 這個庫支援的 Pixi 版本是 3.0.11。如果使用比較高的版本會有一些問題,比如出現這樣的警告。