
今、本格的なwebアプリを作るためにAdobe Edge Animateをガッツリいじっています。
なので、しばらくブログの更新が滞ると思います。
Edge Animateもバージョンを重ねて、やっとまともにコンテンツ制作に使えるレベルになってきましたね。
何よりiOSやAndroidのバージョンも上がって、徐々にHTML5への対応度も上がってきました。
そんなわけで、Edge Animateの勉強を始めたんですが、モバイル対応はなかなか苦労させられます。
インターネット初期の「jpgは50KBまで」みたいなレベルじゃないですが、かなり軽量化に神経を使います。
現在の回線状況なら数MBくらいなら全然問題ないんですが、それでも100KBでも減らせるなら減らしたいわけです。
特に本格的なコンテンツになると画像や音声ファイルが増えてしまうので、そこの部分を工夫しないといけません。
画像の方はEdge Animateのスプライトシート機能を使うと容量をかなり減らせて、レスポンスも向上するんですが、音声の方は特にこれといった機能がありません。
スプライトシートとはなんぞやというと、あれです。
ファミコンのマップチップやキャラチップみたいに、小さい画像を一つの大きな画像に集めて適時使いまわすアレのことです。
そうするとファイルサイズやサーバーアクセスを減らせます。
音声でも、スプライトシートのように複数の音声ファイルを一つにまとめて使いまわせば、よりレスポンスを向上させることができます。
そうゆうのをオーディオスプライトと言ったりします。
ですが、Edge Animateでオーディオスプライトを実装するには自力で何とかするしかありません。
Javascriptのライブラリを探して追加してもいいんですが、せっかくタイムラインのあるEdge Animateなので、シンボルのタイムラインを使った方法を考えました。
やり方は割と原始的。
オーディオエレメントをシンボル化してから、オーディオスプライトの区切り秒数と同じ位置のタイムラインにラベルをつけ、そこから同期させてオーディオを再生するような仕組みを作るだけ。
これならEdge Animate上でオーディオスプライトの中身を聞くことができます。
ラベルと同じ位置のタイムラインアクションはこうなります。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//sym.$("○○")[0];の中はオーディオエレメント名を入れてください | |
var audioElement = sym.$("se01")[0]; | |
// オーディオ再生位置 (秒単位) をラベルの位置(ミリ秒単位)に同期させる | |
audioElement.currentTime = sym.getPosition() / 1000; | |
// オーディオトラックを再生 | |
audioElement.play(); |
オーディオエレメント名は適当に変更してください。
簡単に説明すると、getPosition()で再生マーカーがタイムライン上の何ミリ秒にあるか調べ(要するにラベルの位置)それを秒に変換してからオーディオ再生位置プロパティに入れています。
これと一緒に、スプライトの終端には一時停止かループアクションを追加してください。
じゃないと次のスプライトが再生されてしまいます。
こうしておけば、オーディオを再生したい場合は、ラベル位置からライムラインを再生するだけでOKになります。
ただし、プリロードが効かないので、最初のロードだけはクリックイベントなどに絡めてオーディオを再生させてやる必要があります。
これならラベル名でオーディオ内容を判別することができますし、タイムラインでスプライトのスライスを作成することも容易ですね。
さて、本来ならこのコードで正常に動くはずなんです(実際PC版ChromeではOK)が、iOSではどうも上手くいかないようです。
理由はわからないのですが、タイムライントリガー時にplayと同時にcurrentTimeを変更しても無効にされて、直前の一時停止された時間から再生されます。
ついでに言うと再生中にcurrentTimeを変更するとちゃんと変更されます。
ガッデーム!
なので、クリックイベント時にオーディオエレメントのcurrentTimeを変更してから、スプライトシンボルを再生してやる必要があります。
ラベルを使うならクリックイベント時にgetLabelPosition()を使ってラベル位置の時間(ミリ秒)を取得すると良いでしょう。
ちなみに、クリックイベント時にcurrentTimeを変更してあっても、playするタイムライントリガー時にcurrentTimeを変更すると、やっぱり直前に一時停止したタイミングに強制変更されます。
なんじゃそりゃw
とりあえず、オーディオスプライトファイルの終わりに無音を少し入れておいて、アプリの一番最初のタッチで、全体をロードさせておいて、アプリ実行中はオーディオファイルを停止状態にさせずに一時停止状態を維持して使いまわす。
これで、上手くいきました。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//ラベル名 | |
var labelName = "se1"; | |
//オーディオエレメントを包んだシンボルまでのパス | |
var path = sym.getComposition().getStage().getSymbol("audioSpriteSymbol"); | |
//ラベル位置の時間(ミリ秒) | |
var labelTime = path.getLabelPosition(labelName); | |
// タイムライン(ミリ秒)とオーディオ(秒)を同期 | |
path.$("seSpriteAudio")[0].currentTime = labelTime / 1000; | |
// オーディオ再生 | |
path.$("seSpriteAudio")[0].play(); | |
// ラベル位置からタイムラインを再生 | |
path.play(labelName); |
大体こんな感じでタッチイベント中に書くとiOSでも動きます。
でも、いろいろ調べているうちにwebアプリとしてHTML5を使うなら、Web Audio APIを採用した方がいいかなって思うようになりました。
もうちょっとオーディオの扱いに慣れたら、もっと上手い方法を考えてみます。