一つのhtml内に Adobe Animate HTML5 canvas コンテンツを混在させる方法



ざっとwebを探したのだが見つからなかったので試行錯誤して試した。
結論から言うと可能。



#概要
複数のFLA/XFL file から書き出しすると, exportRootとかcanvasとかstageとかlibとかがバッティングして普通は使えない。

原理的にはexportRootやstageをバッティングしないように変えてやれば良い。


#目的

一つのhtml内に, html5 canvasを複数並べて, flashみたいなコンテンツを表示したい時は結構多いハズ。swfの時は普通に複数並べられたのだが, Adobe AnimateのHTML5 Canvasになってから単純にはやれなくなった。
おそらくは需要があると思うのだけど、やってるという記事がどこにも見つからなかったのでこちらにまとめて後人の役に立てばいいなと。


#原理
Flashの時の"_root"に相当するものはcreatejsでは exportRoot という変数になっている。
じゃぁこれ複数設定できればいいじゃん、とか思うのだけど、いきなりそれができるわけじゃないのがイケてない。

順番に紐解いていくとAnimateが作るhtml/jsの中に, 個別のFLA/XFLを認識するためのIDがあるようで、ここから compositionというものを引っ張って, compositionからlibraryを引っ張り, libraryの初期化や, libraryにcanvas(=stage)を紐付ける処理などを書いてやることで、ようやくexportRootを個別に扱うことが可能になる。

canvas, stage, exportRoot, libraryなどが個別に扱えるのであればもうあとはそれぞれのcanvas内ではコンテンツが自在に動くため、個別のコンテンツに対してjavascriptでコントロールできる。もちろんjavascriptにはcanvas毎を仕切る仕組みはないため、一つのcanvasから他のcanvasへのアクセスも可能。



#説明
参考ソースを
https://github.com/nariya/multianimatesample
に置いた。

今回3つのxfl
hoge.xfl
hoge2.xfl
hoge3.xfl
を作成して、fuga.html内に3つのcanvasを並べて, hoge, hoge2, hoge3のコンテンツを表示することとした。


それぞれのxflからパブリッシュされたhtml/jsは 
- hoge.html
- hoge.js
- hoge2.html
- hoge2.js
- hoge3.html
- hoge3.js

となる。これらを適当にツギハギしてfuga.htmlを作る。

(スプライトシート作るパブリッシュとかの場合にはfuga.htmlはそれに応じてちょっと変わってくるわけだが原理としては変わらない。)


hoge.htmlの中には
- init()
- handleComplete()

の２つの関数がある。(hoge2, hoge3についても同様)

これを, 名前だけバッティングしないように fuga.htmlに並べる。
(init2, handleComplete2,など適当に名前をつける)

html最下部に, animation_conatainer, canvasなどがあるので、これも名前がバッティングしないようにそれぞれのxfl用に作成する(width heightなどは適宜個別のhtmlの数値に合わす. むしろ個別のhtmlからコピペして, canvas名などだけリネームするほうが楽)

3つのxflの"init()"関数を一通り呼んでやる.
今回のfuga.htmlでは initの中で init2, init3を呼んでいる。


handleCompleteも3つコピーしているが...実際にはmakeResponsiveの処理などは3つ分まとめて書いたほうが良い。今回は説明をわかりやすくするために3つ分をコピーして実行している。

一つにまとめる場合, lib, stage, w, h など各種変数名がバッティングしないように適宜リネームしたりなどする必要がある...まぁあたりまえ。

また、canvas, stageなどが元のhtmlではglobalに定義されているので, 3つ分用意する。

```javascript:fuga.html
var canvas, stage, exportRoot, anim_container, dom_overlay_container, fnStartAnimation;
var canvas2, stage2, exportRoot2, anim_container2, dom_overlay_container2, fnStartAnimation2;
var canvas3, stage3, exportRoot3, anim_container3, dom_overlay_container3, fnStartAnimation3;
```


確認していないが, exportRootとcanvas, don_overlay_containerぐらいだけコピーすれば動きそうな予感はする。(が, 確認する労力をかけるほどのモチベーションがなかった)

init, handleCompleteの中で
- canvas
- stage
- exportRoot
- anim_container
- dom_overlay_container
- fnStartAnimation

と記載されているところを, canvas2, stage2などに適宜リネームする。

これで動くはず。
他のcanvas上で動いているコンテンツにアクセスするためには exportRootを使ってやれば良い
サンプルでは

```javascript:hoge2.js
			exportRoot3.textbox.text = "Hello from canvas2";
```


の様な処理でtextを変更しているが、もちろんstop, play など各種の制御も, 変数を入れたりとかも普通にできる。




#もうちょっと追記
とりあえずそれで動く、ってのはわかったと思うのだけど...Adobe Animate の内部処理について

個別のXFLについてIDを持っているらしく、そのID経由で諸々とアクセスしてやるのが本来きれいな処理になりそう

```javascript:fuga.html
	var comp=AdobeAn.getComposition("824BA9F098894E8684AE3429307AC0B0");
	var lib=comp.getLibrary();
```


こういう感じでcompositionを持ってきて、そっからlibraryを引っ張り

```javascript:fuga.html
function handleComplete(evt,comp) {
	//This function is always called, irrespective of the content. You can use the variable "stage" after it is created in token create_stage.
	var lib=comp.getLibrary();
	var ss=comp.getSpriteSheet();
	exportRoot = new lib.hoge();
	stage = new lib.Stage(canvas);
	stage.addChild(exportRoot);	
```

stage, canvas, exportRootを設定しているわけですな。
canvasはhtml5の要素なわけだから当然globalにあるとして, stageもglobalはしょうがないが,  exportRootとかはstage.exportRootみたいな感じで取るほうが名前空間を汚さないかもしれない....

あと書いてないけどスプライトシート作ったりする時は当然バッティングしないように書き出すディレクトリとかファイル名かぶらないようになってないとおかしくなると思うよ。