はじめに
Flash、ついに終わりますね(悲しみ)
3年前、同じようなコンセプトでこんなものを作ったんですが、
Adobe Animateのバージョンが上がり、書き出されるコンテンツの構造が変わっていたりするので
Creap.jsの進化版
Adobe Animate製CreateJSコンテンツを、pixi.jsで再生するプラグイン
pixi-animate-player
を改めて作ってみました。
目指すのはCreap.jsと同様
- アニメーションをAnimateで作りたい
- でも動作速度は改善したい
です。
ドキュメントとサンプル
使いかた
用意するもの
- CreateJS 1.0.0
- pixi.js 5.3.2
- pixi-animate-player 2.1.2
- Adobe Animateでパブリッシュしたコンテンツ一式
ファイルの読み込み
<script src="https://code.createjs.com/1.0.0/createjs.min.js"></script>
<script src="pixi.5.3.2.min.js"></script>
<script src="pixi-animate-player.min.js"></script>
<script src="content/content.js"></script> <!-- Adobe Animateでパブリッシュしたコンテンツ一式のjsファイル -->
- 最初にpixi.js及びCreateJS(順不同)
- 次にpixi-animate-player
- 最後にcontent/content.js
という順で読み込むようにしてください。
実行
var player = new PIXI.animate.Player(
"[conposition id]", // "lib.properties.id" in Animate content.
"[root class name]", // Root class name of Animate content.
"[content directory path]", // Directory path of Animate content.
{
useSynchedTimeline: true,
useMotionGuide: false
},
{
antialias: true
} // Options of PIXI.Application.
);
player
.prepareAsync({
crossOrigin: false
})
.then(function() {
player.play();
});
-
[conposition id]
content.js内でlib.properties.id
として定義されている32文字くらいの文字列。 -
[root class name]
root
に該当するMovieClip
クラス名。
Animateが勝手に付けるので、大体はflaファイルと同名になっているはず。
(content.flaであればcontent
) -
[content directory path]
「Adobe Animateでパブリッシュしたコンテンツ一式ディレクトリ」の
HTMLから見た相対パス、または絶対パスのいずれか。
絶対パスを使用、かつアセットが別サーバにある場合は、player.prepareAsync
の引数のcrossOrigin
をtrue
にする。
プラグイン自体にPromise polyfill
は含めていないので、
必要があれば別途読み込んでください。
パフォーマンス
ここのBenchmarks
を見てもらえると分かりますが、
ざっくりと重い処理になればなるほど効果が高いといって差し支えないかなと思います。
例として、私のPCでのFPSは
CreateJS | pixi-animate-player(webGL) | pixi-animate-player(canvas) | |
---|---|---|---|
100インスタンス | 60 | 60 | 60 |
1000インスタンス | 52 | 60 | 56 |
1000インスタンス(着色) | 42 | 58 | - |
5000インスタンス | 12 | 25 | 14 |
のような感じで、基本的にはwebGLの力での高速化が大きく、
加えてpixi.jsのレンダリング処理の最適化も若干利いているという感じでしょうか。
本来pixi.jsであれば、5000インスタンス程度ではFPSは下がらないんですが、
タイムライン+入れ子という構造が処理に強く影響しているような印象です。
仕組み
ここからは内部構造についてちょっと。
使えればいいよって方は読み飛ばしてください。
処理フロー
CreateJSの処理フローはざっくりと
- アセットのプリロードやらをして
- ティッカーが回って
- プロパティが変化して
- レンダリングされて
- 2に戻る
のような形です。
pixi-animate-playerでは、このフローが
- CreateJSのアセットのプリロードやらをしつつpixi.jsの準備をして
- CreateJSのティッカーが回って
- CreateJSのプロパティが変化すると同時にpixi.jsのプロパティも変化して
- pixi.jsでレンダリングされて
- 2に戻る
のようになっています。
ユーザスクリプト(flaファイル上でタイムラインに実装するスクリプト)は、
そのほとんどが描画内容を変化させるために実装しているものですので、
最終的な描画内容が確定するまではCreateJSに任せてしまい、
レンダリングだけpixi.jsで横取りすればいいや、という考え方です。
本来はCreateJSを完全にエミュレートした方が処理量が少なくなるのですが、
全てのクラスを完全に実装しない限り、ユーザスクリプトに対応しきれない部分があったので
このような形を採っています。
唯一、ユーザのインタラクションイベント(タップなど)だけは、
イベントを受けるのがpixi.jsのオブジェクトになるため、ひと手間加えた処理をしています。
プラグインの構造
上記フローを実現するために
-
createjs.DisplayObject
継承クラスのインスタンス1つ(以下A)につき
PIXI.DisplayObject
継承クラスのインスタンスを1つ(以下B)、対になるように生成、
(e.g.createjs.MovieClip
->PIXI.Container
) -
Aのプロパティが変化すると同時に、Bの対応するプロパティを変化させる
(e.g.A.scaleX
->B.scale.x
) -
Bが受けたインタラクションを、Aに対するインタラクションとして処理する
(e.g. ユーザアクション ->B.emit('pointerdown')
->A.dispatchEvent('mousedown')
)
※これはイメージで、実際には登録されたハンドラを実行しているだけ
といったことをしています。
おわりに
端末の性能も向上してきたので、Animate製CreateJSコンテンツそのまま再生でも問題ないかもなーと思いつつ
どこかで何かの役に立てばいいなと。
AnimateからのwebGL書き出しはいつになったらスクリプト対応するんですかね?
みんなもAnimate使ってね!