クリスマスツリーを iPhone でも見れるようにしたよ


ジェバンニ仕事で、http://koebu.com/event/xmas/2010/iPhone / iPad に対応させました*1

目からビーム出して頑張ってる最中のツイートまとめ

iOS では、ユーザアクションを伴わない、audio.play() やaudio.load() は機能しない。さらにpreloadとautoplay属性も無効化されている http://bit.ly/fmLf5y in Device-Specific Considerations
http://twitter.com/uupaa/status/15433471463784449

なんかね、PCブラウザのように、audio.play() 呼んでも audio.load() 呼んでも動かなくて、色々ググッたんだよね。

iOS でBGMは、そのままでは自動再生できないので、ユーザに画面をタッチしてもらう必要がある
http://twitter.com/uupaa/status/15433728247468035

この時点では、window.addEventListener("touchstart", function() {...}, false) でイベントかすめとって、その隙に色々やったらどうなんだろう? とかモヤモヤしてた

つまりiOSでは、なんとしても画面にタッチしてもらって、そのタッチイベントハンドラ内で、audio.load()を含めゴニョゴニョまとめてやってしまって、ある程度までオーディオデータの読み込みが進んだら(canplayイベントが発生したら)、play()で再生すればできるのかな?
http://twitter.com/uupaa/status/15434696645156864

いやいやいやいやいや… ソレ無理あるだろうと。この後思い直すわけですが。

クリスマスツリーをiPhone対応にするためにゴリゴリ書き直してる。
http://twitter.com/uupaa/status/15439252250697728

寂しさと空腹に負けてツイート

iOS

ドーパミンドバ〜 した時のつぶやき

そもそも状態遷移が違う

クリスマスツリーのページを、PCブラウザ向けに組んだ時は、

  1. mp3ファイルの一覧をAPIで取得する
  2. 取得したmp3ファイルを裏で読み込み、再生可能な状態になったらプレゼントとして登場させる
  3. クリックで再生開始

といった流れで、状態を管理していたのですが、
Apple の技術資料 http://bit.ly/fmLf5y にも書かれているとおり、ユーザアクションを伴わない形で audio.play() や audio.load() を実行しても iOS では機能しないから、PC用サイトのUIを組む感覚でiPhone用サイト組むと全くダメなことが判明。

モバイルSafariで動かすために、

  1. mp3ファイルの一覧をAPIで取得する
  2. プレゼントとして登場させる
  3. クリックでaudio.load()を実行 canplayイベントを待ってaudio.play()で再生開始

という別の流れを作成する必要がありました。
また、AudioPlayerクラスをPCブラウザ用(XmasPlayer)とは別に用意(XmasMobilePlayer)することで、モバイルSafariでの音声の再生も可能になりました。
# uupaa.js にはOOP的なクラスを作る機能があります。

モッサリをサクサクにする(アニメーションを軽くする)

クリスマスツリーのページのプレゼントボックスは、uupaa.js の uu.fx() を使いアニメーションをさせています。

uu.fx() の本質的なコードは以下のように、style.left と style.top といったスタイル属性を定期的に書き換えるというものです。

function tick() {
  node.style.left = x + "px";
  node.style.top  = y + "px";
}
setInteval(tick, 12);

ただ、left や top をタイマーで書き換える方式では、雪を4つ降らせただけでモッサリになってしまい、とても人前に出せる状態にはありませんでした。
そこで、前々からやりたかった機能(CSS3 Transition) を uu.fx() に組込み、機能強化を行いました*2

http://code.google.com/p/uupaa-js/source/detail?r=994

uu.fx.moveIn(), uu.fx.shlink(), uu.fx.flare(), uu.fx.puff() で、モバイルWebKitなら WebKitTransform を利用するように
uu.fx(node, duration, { tx, ty }) を指定時に、モバイルWebKitなら WebKitTransform を利用するように

従来は、

  • uu.fx(node, duration, { x:100, y:100 }) や
  • uu.fx(node, duration, { left:100, top:100 }) で

アニメーションを作成しますが、
これからは、

  • uu.fx(node, duration, { tx:100, tx:100 }) と

するだけで、uupaa.js が動作環境を判断し、PCブラウザなら tx → left と解釈、MobileSafari なら tx → WebKitTransform:transitionX と解釈するようになります。

つまり、

// これまで
uu.fx(node, duration, uu.env.mobile ? { transitionX:100, transitionY:100 } : { left:100, top:100 })

   ↓↓↓

// これから
uu.fx(node, duration, { tx:100, tx:100 })

スッキリ!

あっそうそう

IE やモバイルSafariで見るとクリスマスツリーが短くて、その他のブラウザだと長かったり、複数の音声を同時に再生してガヤガヤできたりします。
あと、MobileSafariの<audio>は、ボリュームいじれないみたいなので、声が聞こえない時は iPod アプリを起動して音量大きくすると聞こえるようになります。

Boy Meets Girl !!

*1:iOS4.2 以上推奨です。OSが古いと <audio> 動かないかも

*2:この辺は改めて別のエントリで説明します