モバイルWebアプリのこれまでとこれから。

バタバタしていて遅れましたが、先日とあるセミナーでお話しさせて頂きました。

すみません、最初にお詫びします。「Sencha Touch VS jQuery Mobile」というタイトルですが、その内容は一部しか出てきません(--;
別件で調査していた内容を盛り込むでいくと、どんどんそっちが膨らみ、「モバイルWebアプリのこれまでとこれから」という壮大な内容になってしまいました。副題がメインを喰ってしまった!しかも、無駄に枚数膨らんで全部で186p!w

(主題の方を知りたい方は以前作ったスライドのほうをどうぞ)

スライドに盛り込めなかったフレームワークはまだまだ沢山あって、いつかまとめて書いてみたいです。

また、最後の BassS と Webサービスのリベンジ というところ、全く私の勝手な妄想ですが皆さんはどうお考えでしょうか??まだ全然詰め切れてないですが、もう少し考えてみるべき面白そうな議題と思っています。ぜひコメントなど頂けると嬉しいです!

HTML5機能を色々使ったスマホ向けWebアプリを作ってみた話:後編

前回のエントリでもお知らせしたように、ドコモゼミ Webアプリラボのコンテストにアプリを出しました!面白かったら下記ページの いいねをお願いします!

かきまる

スマートフォンを使いながらも、アナログな感触をもっと楽しんで欲しい。そういう想いで考えられた、デジタルとアナログを繋ぐお絵かきWebアプリです。

.

で、今回のエントリでは 前回のHTML5機能を色々使ったスマホ向けWebアプリを作ってみた話:前編 で書き切れなかった残りを解説します。

今回は次のトピックス

  • かわいい文字で表示したい。
  • 音があると楽しい。
  • スマホとタブレット両方対応。AndroidでもiPhoneでも。

Webフォントでオリジナルフォントを使う

Androidがいけてないの一つが、フォントにあると思っています。標準フォントや入っているフォントやが機種によりバラバラ。しかも標準フォントがダサイのが多い。あまりに違うためデザイン的なページの場合、テキストで統一的に表現するのは難しく、画像にしないといけなくなります。

画像にすると色々問題があります。まず変更がめんどくさい。文言ちょっと変更する度に画像を書き出さないといけない。さらに、昨今の高精細ディスプレイ用に2種類の解像度の画像が必要。そしてモバイルの場合特に重要なのが、ページサイズが増えること。画像が多くなると必然的にページサイズが増え、3G回線などでのモバイルではロード時間が遅くなってしまいます。

じゃあ、どうすればいいのか。そういう時に、Webフォント が使えます。Webフォントとは CSS3 から導入された仕様で、これまではOSにインストール済みのフォントしか使えなかったのが、必要に応じてWeb上からフォントデータをダウンロードして表示できます。これを使用すると、機種毎にバラバラなAndroidでも、iOSでも、PCブラウザでも同じフォントで表現できるようになります。

ただ、日本語フォントのように膨大な数があるとフォントデータが増え、画像データよりむしろ重くなることがあるので注意が必要です。必要な文字だけのフォントデータのする、などの工夫が必要です。今回のかきまるでは、ひらがなのみなのでサイズは woff 形式で11kに収まりました。この程度なら、画像を複数枚用意するよりも少ないサイズでいけます。また、フォントデータをキャッシュさせれば、別の文字が増えたとしても新たなダウンロード時間は増えません。

前回のひらがなの書き順を表現するため、文字データをSVGで作っていたので、それを元にWebフォントにしました。Webフォントに使える形式は幾つあります。最近だと WOFF が標準ですが、古い形式のために ttf や svg形式のものも用意し、CSS記述でフォールバックするようにしておくとベターです。

SVGからWebフォントの作り方はこちらを参考にしました → アウトラインのSVGからフォントを生成 #かな書いてみるFontForge の出力形式に woff、svgなどを追加すると、自動でその形式で出力してくれます。

ちょっとはまったのが、フォントデータにするときはアウトラインデータの方が良い、ということです。まぁ、当然なのですが。。。アウトラインから変換することを前提としているので、stroke の lincap や linejoin などは無視されます。今回の文字データは、書き順アニメーションのために1本のパス(stroke)で書かれていたのですが、そのまま変換するとうまくいきませんでした。そこで、フォント用に別途アウトラインデータも作成しました。

音を再生する

photo by vancouverfilmschool (CC BY 2.0)

Webで音を再生するには二つの方法があります。簡単なのが HTML Audio要素を使うこと。スクリプトからも操作でき、簡単な音声の制御ができます。もう一つが Web Audio API を使用すること。こちらはもっと複雑なことが可能で、合成やフィルタリングなどを使用してWeb上でシンセサイザーのようなことも実現できます。

ただし、Web Audio API はモバイル端末ではまだまだサポートが厳しい現状です。iOS 6から一部制限付きで使えるようになりましたが、Androidでは全然だめ。ということで、スマホ向けWebアプリは 今のところ HTML Audio要素一択という状況です。

HTML Audio要素ならスマホでも盤石か、と言うとそういうわけでもありません。スマホの限られたリソース(CPUや帯域)では、音声データのダウンロードやデコードで少し時間がかかる場合があります。そこで予めデータをプリロードしておきたいところですが、これも色々と制限されています。詳しくは 過去エントリ iOS/Android で HTML5 の audio/video を任意のタイミングで再生する方法 でも書いたのですが、audio を play する前に、load しておくことで対応できます。

「かきまる」では、当初 最初のページにタッチしたタイミングで全音声データをロードしていたのですが、それだと重すぎて最初のページめくりが固まってしまいました。そこで、各ひらがの書き順ページへ遷移するタッチイベントをトリガーに、次の動物の名前の音声データをロードするようにしました。書き順を表示している裏でダウンロードされるため、次の動物にいったときには、すぐに再生されます。

この方法の欠点として、書き順を表示しきる前に次々にページをめくると音声再生が追いつかない、という問題がありますが、これはもう致し方なしとして諦めました。また、Android Chrome の ver 25 くらいまではこの方法でうまくいっていたのですが、最新版の 27にすると事前 load が効かず、play時にのみロードされるようになってしまいました。

他にも、Galaxy Nexus(Android 4.2.2)の標準ブラウザと Chrome を組み合わせると、ブラウザ終了時やスリープ時に最後に再生した音声が勝手に再生される、というとんでもないバグがあったりします。しかも通知でも再生されるため、メール着信などある度に ”おおありくい〜” とか勝手着信音となってしまったり(ーー;; 他の端末では起きなかったため、対処は見送り。。

スマホ/タブレット/Retina対応。Androidでも。

一通り動くようになってから、最後に スマホ(縦横)と、タブレット(縦横)でもちゃんと見えるよう、CSS メディアクエリを使って調整しました。Android でもきちんと表示されるよう対応させるのに苦労しました。

SVGを画像として使う。

画像をスマホ/タブレット用に最適化すると、それぞれのRetina用も考えると、スマホ or タブ x 2解像度 = 4パターン必要になります。さらにそれの縦横まで対応すると、1つの画像に8パターンも必要になってしまいます。(実際には縦横は同じ画像を縮小で表示することが多いでしょうが)

今回は画像に SVGを使ったため、1パターンさえあればよいので非常に楽でした。Android 2.x は SVGに対応していないのですが、ここはもうばっさり切りました。Android 4以上なら問題なし!と言いたいところですが、まだ落とし穴があります。

SVGをWebページに埋め込みで使う場合、幾つか方法があります。

  • OBJECTタグで使う
  • IMGタグで使う
  • インラインSVGにする

古いブラウザなどの場合、IMGに使えなかったりするので、OBJECTタグを使用する必要がありますが、スマホの標準ブラウザ(Chrome)ならIMGで問題ありません。OBJECTタグにする問題点は、外部ドキュメントになるため、UIイベントがそちらに取られてしまうことがあります。また、インラインSVGにすると元ページにSVG要素を埋め込まないといけないため、画像の差し替えが煩雑です。なので、単に画像として使う場合は IMG要素として使うのがオススメです。(この節のSVGと書いてある画像も実はIMGタグでsvgを指定しています)

IMGタグでSVGを使う場合、画像サイズの指定はIMGタグで行います。width/heightの属性か、CSSの属性で指定できます。通常、widthとheightを指定すると、元画像のアスペクト比を保持したままスケールします。しかし、一部のAndroid標準ブラウザでは、アスペクト比が保持されず引きのばされてしまいます。iOS と Android標準ブラウザの表示違いは下の図のようになります。

Android標準ブラウザ

そこで svg ファイルの viewBox を見直しました。svgタグには、どの範囲を表示するか指定する viewBox という属性があります。このviewBox のアスペクト比と実際に表示させる画像のアスペクト比を一致させることで、この問題に対応することができます。

アイコン

一部のアイコンにも、SVGフォントを使いました。IcoMoon などを使えば簡単に導入できて便利です。ただし、Androidでは要注意です。

通常、Webフォントをアイコンに使う場合、特定の文字コードをアイコンに割り当てます。Unicodeでは、外字エリアとして私用領域という名称で U+E000〜U+F8FF、U+000F0000〜U+000FFFFDなどが割り当てられているので、これを使うことが多い。前述の IcoMoon はこの外字エリアを使っていて、U+E001 から埋めていきます。

ところが、一部Andoroid(Softbank端末など)は、この外字エリアに独自のアイコンを定義してたりします。→ 携帯電話の絵文字

U+E001 は ソフトバンクの絵文字ともろに被っています。今回は時間が無かった & ドコモ向けなので、残念ながら対応は見送りましたが、IcoMoon などを使う場合、コードには十分気をつけてください。

メディアクエリ

SVG画像のスケールは上記の対応で可能になりました。次は、メディアクエリを使い、幅に応じて画像や文字の大きさを変更します。メディアクエリで端末サイズを判定するには主に二つの方法があります。

  1. min-width, max-width で判定する。
  2. min-device-width, max-device-width で判定する。

1つ目の方法は、windowの幅で判定するのに対して、2つめは、端末の幅で判定します。PCブラウザから見るとどちらも同じように動きますが、スマートデバイスでみると大きく異なります。特に回転した場合に違いが出ます。デバイスの向きを横に回転したとき、1の方法で横幅の変更を検知し、レイアウトを変更できます。しかし、2つめの方法では端末自体の幅は固定のため、回転しても変更されません。そのため、向きを判定するためには orientation:portrait / orientation:landscape を組み合わせて使用します。 なお、この orientation は厳密には向きを見ているのでは無く、縦長か横長なのかを見ているだけです。なので、PCブラウザで縦長/横長を変更しても反映されます。

どっちの判定を使えば良いか、というと前者をオススメします。というのも、これまた一部のAndroid標準ブラウザでは、device-width を正しく認識しません。例えば、Galaxy Nexus, S2, S3 なんかでは、window.innerWidth は 360px なのに、メディアクエリの device-width は 320px として認識されます。細かい調整をする場合、正しく認識されないのは致命的です。また、device-widthを使用する場合は orientation も同時に指定しないと意味が無いため、記述も長くなり、お勧めしません。

まとめ

Webアプリでも表現が幅がだいぶ広がってきました。今後、WebRTC や WebGLとか使えるようになったらもっと凄いものができるようになると思います。まだ Android Chromeでもデフォルトはオフ、Safariは全然うごかない(今日発表の iOS7 で対応がでるかも!?)

現状では「かきまる」のようなシンプルなものでも、意外と苦労しています。スマホ向けWebアプリで、なめらかなUIや、複数端末への対応は骨が折れます。特にAndroidは本当にツライのでGoogleさんマジでなんとかしてください(切実

HTML5機能を色々使ったスマホ向けWebアプリを作ってみた話:前編

昨日、ドコモがやっているWebアプリコンテストのノミネート作品が一般公開されました。

私も、デザイナさんと協同して作品を一つ出しました!面白かったら下記ページの いいねをお願いします!

かきまる

スマートフォンを使いながらも、アナログな感触をもっと楽しんで欲しい。そういう想いで考えられた、デジタルとアナログを繋ぐお絵かきWebアプリです。

.

子供達が家の中でスマホだけをいじって遊ぶのでは無く、実際のリアルな紙と色鉛筆で本物の感触で遊んで欲しい。そのきっかけをスマホアプリで与えられないか?というモチベーションで作られました。そのあたりのコンセプトはデザイナさんのアイディア。私は主にその実装担当です。

そういう狙いはあるのですが、簡単に言ってしまえば紙芝居形式で動物の絵を表示して、それをお手本に絵を描く、という至ってシンプルなアプリです。

何も考えずに作れば、複数のWebページを遷移する単なるWebサイトとしても実現できます。しかし、それじゃあつまらないので、今回はそこに色々と実験的な要素を盛り込みました。

  • ページめくりをかわいくしたい。
  • ゲーム的な要素もちょっとあると面白い
  • ひらがなの書き順も同時に教えられたら。
  • かわいい文字で表示したい。
  • 音があると楽しい
  • スマホとタブレット両方対応。AndroidでもiPhoneでも。

これらの要望を HTML5 Webアプリとしてどうやって実現するか、が私の課題でした。今回のエントリーではその実装について簡単に解説します。要望があれば連載で詳しい内容も続けていければと思います。

カードをめくるように表現する

スワイプで次のスライドが表示されるようなアプリは良くあります。Webでもそういう表現が増えてきました。多用されているためやや食傷気味で、そのまま使うのは面白くない。ただ、スワイプジェスチャーでページをめくるという認識は一般にもだいぶ浸透しています。そこで、そのジェスチャーはそのままに、表現をすこし工夫しました。ページをカードに見立て、カードをめくるように次々と下のカードが出てくるような表現にしてみました。

スライドのライブラリは沢山あるのですが、カードのような表現ができるライブラリが見つからなかったため、一から自作しました。タッチイベントのドラッグを処理するには、jQuery プラグインの Hammer.js が便利です。それに CSS Animation を組み合わせて実現しています。

使ってみると、予想以上にカードページングはスマホと相性が良い気がします。後から気がついたのですが、スマホ用 Google Chrome のタブなどもカードアニメーションしていますね。このカードページングは jQuery プラグインとして作成したので、整理できたら公開してみたいと思います。

スロットゲーム

動物をしりとり形式で繋げよう、というアイディアは当初からあったのですが、最初の動物(文字)をどうやって決めようか、と悩みました。ここにゲーム要素を持ってくることにしました。ひらがながスロットのように表示され、タップすると少し遅れて止まります。このスロットもライブラリとして作成したので、公開できればしたいと思っています。スロットの向き、速さ、止まるタイミングなどを色々検討するため、各種設定値で変更できるようにも作りました。

このスロットの中身の文字は、実は普通のテキストです。当初、画像にしていたのですが後述のWebFontを使うことで、文字だけで表現することができました。

また、スロットのタップイベントにも一工夫が必要でした。実際に子供達に使ってもらうと、タップが反応しない、という問題が起きました。スロットを止めるという動作の特性上、狙って押すと結構力が入ってしまうんですね。そうすると、タッチがぶれるんです。ぶれると、タップイベントではなく、ドラッグイベントとして認識してしまうというのが原因でした。これは、以前 @IT にも書いた記事 タッチUXを実現する7つのポイント で、自分も指摘していました。自分で書いてるのに考慮漏れとは情けない。。。

このタップの問題も、前述の Hammer を使うと各種閾値を調整すれば解決できます。ついでに、アイコンやボタンなどについてももう一度当たり判定エリアや閾値を見直し、子供でもタップしやすいように調整しました。

ひらがなの書き順を表示する

ひらがなの書き順をアニメーションで表現するのには、少し悩みました。一番実装が簡単なのは、各コマを用意してcanvasにパラパラアニメのように順次描いていく方法です。しかし、それでは文字が増えたときに大変です。そこで次に考えたのが、SVGのモーフィングを使うことです。Raphaël を使えば、割と簡単に実現できます。しかし結果からいうと、これはうまくいきませんでした。モーフィングの補完をちゃんと指定すればいいのですが、全文字でこれを何コマか設定するのはとてもやってられません。

そこで、ひらがなをグリフではなく、単1のパスの組み合わせとして作ることにしました。それをSVGのパスで表現し、書き順でパス要素を上から並べます。「あ」ならば、1つめの要素が横1本のパス、2つめの要素が縦1本のパス、3つの目の要素が、ぐるっとまわるパス、というような感じです。先ほどの Raphaël を使えば、長さを指定して、パスのサブパスを取得することができます。これを使用して、各パスのサブパスを段々伸ばしながら描画しています。

この文字データを作る際に、どうせならあ段だけじゃなくてひらがな全文字作ろう!といってデザイナさんが頑張って作ってくれました!当初50文字だけかと思ってたら、濁音とか半濁音とか、小さいかなとか意外とあって大変そうでした^^; ここでかなデータをSVGで全部作ったので、これを元に SVG Fontをつくり、後編の WebFontへと繋がります。



簡単に説明するつもりが、予定以上に長くなってしまいました。
ということで、続きは後編で!

→ 後編書きました! HTML5機能を色々使ったスマホ向けWebアプリを作ってみた話:後編

iOS/Android で HTML5 の audio/video を任意のタイミングで再生する方法

HTML5 で追加された audio/video 属性によって、プラグインレスで動画や音声の再生が可能になったことはよく知られていますが、モバイル(スマホ)で、その再生タイミングの制約が厳しいことは案外知られていません。これは以前、当Blogでも HTML5 x Touch UI の UXを考える(補足) の User action event restrictions でもチラッと書きました。またしてもこの制約に苦しめられながら、なんとか解決策を見いだしたので、GW最中にも関わらず久しぶりのエントリーです。

まず、本家 Apple のドキュメントにも以下のようにあります。
iOS-Specific Considerations

In Safari on iOS (for all devices, including iPad), where the user may be on a cellular network and be charged per data unit, preload and autoplay are disabled. No data is loaded until the user initiates it. This means the JavaScript play() and load() methods are also inactive until the user initiates playback, unless the play() or load() method is triggered by user action. In other words, a user-initiated Play button works, but an onLoad="play()" event does not.

(超意訳)

iOS の Safari では、ユーザーが携帯網で重量課金されるかもしれないから、preload と autoplay は効かないよ。ユーザーが何かアクションしないと、JavaScript での play() や load() もダメ。つまり、再生ボタンを押して play() を呼べるけど、onload で play() しても無効だから。

このユーザーアクションというのが結構厳しい。touch/mouseイベントの直接のハンドラ内でしか効きません。setTimeoutなどのタイマーを挟むともうアウトです。

例えば、以下のようなコードは再生できます。http://jsfiddle.net/dsuket/jTh3v/

var playBtn = document.getElementById('play');
playBtn.addEventListener('click', function() {
    audio.play();
}, false);

しかし、これにタイマー挟むと再生されません。 http://jsfiddle.net/dsuket/Ny9Xz/ (PCブラウザでは再生できます)

var playBtn = document.getElementById('play');
playBtn.addEventListener('click', function() {
    setTimeout(function(){
        audio.play();
    }, 2000);
}, false);

これは setTimeout だけじゃなく、例えば transitionEnd などのアニメーション関連のイベントなどもダメです。そうすると、アニメーション終了時のタイミングで音声を再生したい場合に非常に困る。

そこで、以下のようにすると再生できます。http://jsfiddle.net/dsuket/rWpM7/

var playBtn = document.getElementById('play');
playBtn.addEventListener('click', function() {
    audio.load();
    setTimeout(function(){
        audio.play();
    }, 2000);
}, false);

ポイントは、setTimeout の前に load() することです。play() メソッドは内部で自動的に load が呼ばれるのですが、タイマーハンドラの中ではこの load が抑止されているようです。そこで、ユーザーイベントが発生した段階ですぐに load() だけ呼び出し、後は任意のタイミングで play() すればOK!

なお、ドキュメントonload のタイミングで自動再生したい、というのはやはりできません。そこで、少し画面フローを工夫して、最初にスプラッシュ画面を用意し、タップしてもらうようにします。そのタップイベントハンドラの中で、オーディオファイルをロードします。HTML5 Webアプリでよく使われる Single Page Applicationの場合、ここで必要なオーディオファイルを全部ロードしてしまうと良さそうです。そうすれば後は好きなタイミングで音声を再生できます。

audioについての説明でしたが、videoも同様の問題があります。検証できてませんが、同じようにすれば対応できそうです。

ただ、audio/videoの自動再生や再生タイミングはOSバージョンでコロコロかわります。そもそも iOS4.1、Android 2.3 までは setTimeout の中でも再生できました。それが iOS 5、Andoroid 4 あたりから再生できなくなりました。バージョンが違えばこの load を切り離す方法もまた使えなくなるかもしれません。十分検証には気をつけてください。


参考:

ネイティブよりも速いと評判のfastbookの裏側を調べてみる

本記事は、Sencha Advent Calendar 2012 の23日目の記事です。1日遅れでごめんなさい!あ、今日であってた(;´▽`A 当初完走は無理なんじゃないかと思ってたけど、みんなのがんばりで完走目前!おめでとうございます!

Sencha Touchで作ったネイティブよりも速いfacebookアプリ「fastbook」が話題になっていますね。


f:id:dsuke:20121223112253p:plain

ネイティブを凌ぐすごいパフォーマンスに驚きますよね!これらは実際にはどんなコンポーネントを使って作られているのかすごく気になります。そこで、ちょっと調べてみたいと思いました。

ネイティブアプリ向けパッケージが、https://github.com/extjs/fastbook にあるようなのですが、メンテナンス中と出てアクセスできません。。ソースみたかった。。。2012.12.26追記: 今見るとアクセスできますね。けど、本当にWebViewでラップしただけで中身はWebから表示してるだけでした。つまりJSのソースは無い) 仕方ないので公開されているものを解析しつつ推測してみます。

基本的に3つのスクリプトファイルからできているようです

  • index.js: 他のスクリプトやCSSを読み込むローダー
  • app.js: アプリケーション本体
  • sdk.js: Sencha Touch SDK(3.0alpha!)

app.js にアプリのロジックが圧縮されて入っています。圧縮と言ってもそれほど複雑な物ではないので、Webインスペクターで Pretty print すれば、まあなんとか読めます。気になるのは、sdkですね。Ext.versionを見てみると、versionが "3.0alpha" とあります!まだ一般公開されていない、次期 Sencha Touch で作られてるんですね!

とりあえず app.js を記事で触れられている改善点を中心に見てみました。

パフォーマンス改善のポイントはいくつかありますが、特に無限Listコンポーネントが重要のようです。これは最近、Sencha Touch 2.1で改良された無限ListコンポーネントWhat’s Coming in Sencha Touch 2.1)のことかと思ったら、実はそうでもないようです。

Sencha Touch 2.1.0 の SDK に含まれる examples に、touchtweets というTwitterアプリのサンプルがあります。これは新しい無限リストに対応しているそうです。(オンライン上のデモはまだ2.0.1のようだ)

fastbookではiframeを使ってDOMツリーを分割したとあります(実際はobjectタグだった。iframeではなくobjectなのはなぜだろう?)。しかし、先のサンプルのリストはiframeではありませんでした。fastbookで使われているのは「Sandboxコンテナー」というまったく新しい機能のようです。残念ながらまだSDKには入っていません。 Sencha Market なんかで出してくれないかなー、と期待してます。

次の、TaskQueueは、Ext.TaskQueueのことですね。これはSencha Touch 2.1から新しく追加された機能です。複数のDOM要素の操作をバッチ処理のようにまとめることで、DOMのリフローとリペイントを最小化するようです。リフローについては ブラウザ動作の理解-リフローとリペイント及びその最適化 に詳しくあります。ただ、まだこのクラスはAPIドキュメント上はprivateとなっていて、フレームワーク内部での利用しか推奨されていません。

次に AnimationQueue を追加したとあります。これもfastbookのための新規クラスです。これは内部に taskQueue と idleQueue の二つのキューを持ち、taskQueueがある間はそれを実行し、taskQueueが無くなったら idleQueue を実行する、という仕組みでアニメーションやロードの処理を分割しているようです。特にアニメーションに特化した機能では無く、汎用的な仕組みなため、これも早く標準APIへ組み込んで欲しいですね。

Web Workerは、Ext.Xhrという新しいクラスに組み込まれています。また、これ用に xhr-worker.js が読み込まれています。このスクリプトでWorkerとのmessageやりとりをしているようです。Web WorkerではAjaxでのリソース取得、デコードを行っています。元々Ajaxで非同期通信ではあるのですが、WebWorkerを使うことでUIスレッドから切り離し、よりスクロールの滑らかさなどを維持するようです。特に現在のマルチコアプロセッサを持つスマートフォンなどでは有効だそうです。

総じて、やはりfastbookはかなりチューニングされています。通常Sencha Touchで使われるMVCアーキテクチャでのアプリケーションのロード方法とも少し違います。カリカリにチューニングされているからこそ、この性能が出るんですね。

単純にSencha Touchを使ったからといって、皆が皆ここまでのアプリケーションを作れるわけではありません。それはネイティブにとっても言えることでしょう。ネイティブだからパフォーマンスが良い、HTML5(Sencha Touch)だから優れている、というのはナンセンスです。大筋の傾向はありますが、個別事例ではそれが全てではありません。結局は作り手の技術と情熱次第。

そういう意味で、fastbookはSenchaが優れているということではなく、まさしく作り手次第でHTML5でもここまで出来るんだ、ということを証明してくれたのだと思います。

HTML5で出来ないことまとめ 2012年12月版

本記事は、HTML5 Advent Calendar 2012 の12日目の記事です。なんとか本日中にあげれるか・・ アップできた!

業務やらイベントやら本やらで死ぬほど忙しいなか、無謀にもHTML5 Advent Calendarに参加してしまった@dsuketです。こんばんわ。

先月の段階ではここまで修羅場になるとは思わなかったのですが、師走は恐ろしいものですね。年末にこんな首を絞めるイベントが山ほど各所で行われているとは、つくづくエンジニアはM属性だと思いました。

本ネタは始めは「HTML5で出来ること」にしようかと思っていたのです。が、そんな話は山ほどある。もはや食傷気味ですよね。そこで逆転の発想で「出来ないこと」にすればいい!と閃いたわけです。さすが良い閃きだな−、俺冴えてる!と思ったのも束の間。念のためググってみると・・・「あれ?いっぱいあるぞ・・( ̄0 ̄;)」

しかし、検索上位に表示されるものをよく読んでみると古い内容が多く、もうそれできるよ(できそうだよ)というのも多くある。日々進化の早いこの業界、2,3年も経つと情勢が大きく変わりますよね。そこで今回は、その先人達の記事を参照しつつ「HTML5で出来ないこと 2012年12月版」としてお送りしたいと思います。

第13回 来るべきHTML5の世界へ(後編)

まず、下記の記事からみてみましょう。2010年12月なのでちょうど2年前の記事ですね。
第13回 来るべきHTML5の世界へ(後編)

HTML5でできないこと

また,マルチメディア機能では,Flashがストリーミング動画を複数のブラウザに表示できるのに対し,HTML5ではその対応ができません。これは,HTML5向けのビデオエンコーディング技術がブラウザメーカで統一されていないためで,Internet Explorer 9Safariなどは「H,264」を,MozillaOperaは「WebM」をサポートしています。さらに,動画機能についても,動画制御や著作権管理,フルスクリーン表示などに未対応であり,マルチメディア機能を中心に実装する動きが活発化する中,できないことも明らかになってきました。

ここで上げられているコーディックの問題は今もあります。GoogleH.264を長期的にサポートをしないと言いだした(GoogleがH.264問題を再説明、IEとSafariにはWebMプラグインを提供へ)かと思えば、MozillaH.264サポートを打ち出したり(Mozilla が H.264 をサポートへ、webM 一本化を断念)、一方OperaはMobileに限っては H.264をサポートしたり(Web specifications support in Opera products 英語版)と混乱の極みですが、これでモバイルでは主要なブラウザが全てH.264をサポートすることになりました。(デスクトップ向けではまだ)

記事中で次に触れている動画制御が、何を指しているのか分かりませんがシークやループも可能です(参考: HTML5のvideo/audio+JavaScript APIテクニック)。DRMは未だ解決していません。GoogleやMSが取り込んではいるようですが、標準化にはまだまだ遠そうです(GoogleとMicrosoftら、HTML5対応のコンテンツ暗号化APIの標準化を申請)。フルスクリーンについては Fullscreen API で標準化が進み、FirefoxChromeSafariでは既にサポートされています。

HTML5でアプリを開発するメリットとデメリット

次の記事はこちら。HTML5でアプリを開発するメリットとデメリット より

HTML5で出来ないことは以下の通り。

  • 写真/動画撮影
  • Bluetoothへのアクセス
  • Gyroscope
  • プッシュ通知
  • バイブレーション
  • メディアファイルへのアクセス
  • バックグラウンドで起動

写真/動画撮影については、WebRTCMedia Capture API で仕様が策定中です。Media Capture API はiOS6でその一部が実装され、遂にカメラが使えるようになりました(参考: iOS6のSafariでサポートされるHTML5の機能)。Androidでもversion 3から対応しています( Android 4の新機能でカメラWebアプリ作ってみた)。残念ながらPC向けブラウザは対応しているものはなさそうです。動画や音声のストリーミングが可能なWebRTCについては、Opera 12、AndroidOpera mobileが標準で対応、Google Chrome がオプションで対応しています。

Gyroscope(ジャイロスコープ)は DeviceOrientation Event Specificationで仕様策定されています。最新のiOS/Androidなら結構動きます。

BluetoothHTML5でデバイス機能を使うためのDevice API にも標準化されていません。今後の追加予定も無さそうです。(追記: あるよ、とご指摘いただきました。末尾で追加しました)プッシュ通知については、そのものではありませんが、Server-Sent Eventsというもので実現可能です。ブラウザでこれを受け取りOSの通知システムと連動すればネイティブアプリのようになるでしょう。

バイブレーションは Vibration APIで標準化されています。未だ Firefox Aurora でしかサポートされてませんが時間の問題でしょう。メディアファイルへのアクセスは前述の通り。バックグラウンドでの起動は Web Workers でできそうですが、現在のところ iOSなどではバックグラウンド中のJavaScriptは停止してしまうため無理そうです。今後の改善に期待!

HTML5で作るiPhoneアプリのできない5つのこと

続いての記事はこちら HTML5で作るiPhoneアプリのできない5つのこと。こちらも2年以上前なのでだいぶ変わりましたねー。ちなみに3が二つあるのは原文まま。

1、clipboardの利用
2、ファイルのアップロード
3、カメラ
3、シェイクイベント
4、加速度センサー
5、バックグラウンド起動

クリップボード欲しいですよねぇ。無いことが意外だとクライアントによく言われます。未だ実装はありませんが、仕様はあります。 Clipboard API and events です。最終更新が去年の2月ですね。なにやらパテントの関係で難航しているようです。。。

ファイルのアップロートは先のMedia Capture APIとFile APIによってiOS6から対応済みです。ただしアルバム内に限る。任意のファイルできません。カメラは前述の通り。シェイクイベントはDeviceOrientation Eventで実現可能です。加速度センサーも同様ですね。

Flashだとここまでできる! HTML5とFlashの機能比較

だいぶ疲れてきました。しかも時間無い。。最後はFlashとの比較。 Flashだとここまでできる! HTML5とFlashの機能比較

クロスブラウザの映像対応
依然として動画コーデックの統一が進んでおらずクロスブラウザに対応した動画コンテンツを提供することが難しい状況です。

これは前述の通り。モバイルはだいぶH.264に寄ってきましたが、デスクトップはまだまだ。

Flash だと縦書きができる

CSS3でwriting-modeがサポートされました。コレを使えば縦書きもできます。こちらの サンプルの右下 Vertical Textで確認できます。

Flash だとタイムラインアニメーションに映像を組み込める

HTML5のオーサリングツールも出始めました。

これらを使えばFlashのようにCanvasアニメーションを作ることが出来ます。

Flash の 3D は進化している

HTML5の3Dも進化しています。WebGLの性能もあがり、便利なライブラリも充実してきています。tree.jsのサンプルで体験することが出来ます。

Flash だとウェブカメラが利用できる

先のWebRTCを使えばHTML5でもウェブカメラが使えます。 WebRTCはブラウザ上でリアルタイムコミュニケーションをするためのフレームワーク。HTML5 Conference 2012
ChromeのCanaryビルドなどで使うことが出来ます。正式サポートまでもう少し!?

Flash 内部で音を生成して再生することができる

HTML5でもこんなドラムマシーンができます。 HTML5 AudioとJavaScriptで作った簡易ドラムマシン

まとめ

時間が無いので手短にまとめます。

  • ここ2年くらいでHTML5で出来ることが随分増えた。
  • 特にモバイルの進化がすごい。
  • これからの2年もきっとすごい進化する。

ということで、本来ならばまだできないことをまとめたいところですが、早くしないと今日が終わってしまうため今回はここまで!

と、してたのですが、やっぱり気持ち悪いので簡単にまとめを追加。
これまで上げた点から、今でもどのブラウザでも出来ない、2012年12月版HTML5で出来ないことは以下の5点!

  1. DRM
  2. Bluetooth通信
  3. OSへのプッシュ通知
  4. バックグラウンドでの起動
  5. クリップボード

個人的には 3,4,5あたりができるようになるともう最高なんだけどなー。これらはまだまだ先の話になりそうです。


追記:
ブクマやtwitterでコメントいただきました。ありがとうございます。
アレが入ってないぞ,このヤロー!とかあるとおもうので、ジャンジャン突っ込んで下さい!

ご指摘ありがとうございます。勉強になります。
System Applications Working Group というので、WebのNative化に対する標準化を進めているそうです。詳しくは小松さんの記事で!WebのNative化に対する標準化が始まる?

Web Applications Working Group では、アプリケーションとして必要な機能の標準化を進めています。クリップボードだけじゃなく、先に挙げたFullscreen APIやFile API、Server-Send Eventsなんかもこれに含まれています。他にも Database and Offline Application APIs、Web Intents、Web Sockets、Widgetsなんかもあります。


ブコメより

んー、出来ないことの範囲が狭い気がするよ、自由にローカルファイルを扱わせろとかOSコマンド実行させろとかあると思うんだけどなあ

確かに、File APIでローカルファイルが扱えるようになった、といっても <input type="file"> か、ドラッグ&ドロップしないとファイルハンドラを受け取れないのは不便ですよね。OSのファイルシステムにそのままアクセスはセキュリティ上問題でしょうけど、サンドボックスみたいな環境があっても良いかもですねー。同様に、OSのシステムコマンド実行も難しいでしょうねぇ。システムコールを呼べるようになると凄いんですが、セキュリティが心配すぎる。。


E4Xが使えない、なんて話しもどこかから。
E4Xありましたね。。。当時は画期的だ!と思ったのですが、JSONが普及してからはXMLがあんまり出番が無くなったような。FireFox もついに打ち切るそうです。E4X は衰退しました


他にもツッコミお待ちしてますー

iPhone5 と iOS6 での HTML5開発についてあれこれ

本日、iOS6がリリースされましたね。明日は iPhone5 の発売日。Mobile Safari も大幅にアップデートされて、Web開発者にとって非常に気になります。

 iPhone 5 and iOS 6 for HTML5 developers, a big step forward: web inspector, new APIs and more で素晴らしいまとめがありましたので、簡単に紹介したいと思います。

iPhone5 

新しい画面サイズ

新しい 4インチ画面になり、解像度は WDVGA (Wide Double VGA) 640×1136px になりました。横幅はこれまでと変わりませんが、高さが 176px 増えました。

新しいシミュレーター

Xcode4が新しくなり、iOS6のシミュレータが出ました。Mac AppStore からダウンロードできます。

何をすべきか

画面サイズに依存したWebサイト(アプリ)は注意が必要です。縦幅が足りなくなります。Google Mapsの例のように、下が切れます。

f:id:dsuke:20120920101847p:plain

レスポンシブWebデザインを使っていても不十分です。通常RWDは横幅に対して使われますが縦には使われていません。 

デバイスの検出

サーバーサイドでiPhone5を検出する方法はありません。userAgent は iOS6 としか判定できません。iOS6 の載った iPhone4/4s と区別不能です。

しかし、JavaScript か メディアクエリーを使えば判定できます。スクリーンの高さが 568px の時は 4インチディスプレイになります。

isPhone4inches = (window.screen.height==568);

また、CSSメディアクエリーとレスポンシブWebデザインのテクニックでiPhone5を判定できます。

@media (device-height: 568px) and (-webkit-min-device-pixel-ratio: 2) { /* iPhone 5 or iPod Touch 5th generation */ }

ホームスクリーンWebアプリ

ホームにWebアプリを追加すると、上下にレターボックスが表示され、今までの画面サイズと同じように表示されます。しかし、4インチに対応したWebサイト(アプリ)でもこうなってしまう問題があります。 

iOS6 での HTML5

ファイル管理

ついに iOS6 の Safari でファイルアップロードをサポートしました! 
input タグの fileタイプで、カメラとギャラリーから画像を選択できます。強制的にカメラにする方法はありません。しかし、accept 属性で 動画と画像の選択は出来ます。
他のファイル、オーディオ、Pagesドキュメント、PDFなどはサポートされません。getUserMedia を使ったライブストリーミングなどもサポートされません。
 
画像やビデオを選択した後に出来ること:
  • form action を使ってポストする。
  • AJAXでアップロードする。
  • File API を使って、クライアントサイドでJS から直接データを操作する。

Web Audoi API

Web Audio API が モバイルブラウザに初めて乗りました。これでゲーム開発などに役立つかもしれません。

Smart App Banner

Webサイトを訪れたとき、サイトに紐付いたアプリがインストールされていなければインストールボタン、インストールされていれば View ボタンを自動で表示できるようになりました。

CSS3 Filter

CSSで画像のフィルター(グレイスケール、ぼかし、ドロップシャドウ、明るさなど)をかけられるようになりました。transforms のようにスペース区切りで複数のフィルタをかけられます。デモ

CSS3 Cross-Fade

iOS6 では新しい CSS Image Values 標準の幾つかをサポートしました。クロスフェードを使うことで、二つの画像を同じ場所に異なる透明度で配置できます。

フルスクリーン Safari

iPhoneiPodiPadは無し)で Safari をフルスクリーン表示することができます。アドレスバーやツールバーが隠れます。しかし、ランドスケープ(横)表示の時だけで、強制的にフルスクリーンにすることは出来ません。

Animation Timing API

requestAnimationFrame として知られている Animation Timing API がサポートされました。これによって setInterval をつかったダサイ描画ループは卒業ですね!

CSS Image Set

低解像度と高解像度用の画像セットをまとめて定義できます。これを使えば、メディアクエリによる切り替えをせずとも、複数の解像度向けの画像を1つで定義できます。retinaディスプレイ対応のための使用ですね。これに対する標準化グループはまだない、とのことで Apple 独自仕様のようです。

Passbook クーポンとパスの配布

Passbook は iOS の新しいアプリです。入場券、チケット、ディスカウントクーポン、ポイントカード、ギフトカードなどを全てまとめて管理します。ネイティブアプリだけでなく、Webサイトからもこのパスの発行ができます。詳しくはこちら  developer.apple.com/passbook 
(日本でも iPhone5 発売日から電通がなにやら仕掛けてくるそうです。これから流行るかもしれませんねー)

Storage API と WebAppの更新

相変わらず IndexedDB は使えず、特に利用可能な新しいAPIはないようです。しかし、幾つか変更点が。
  • Application Cache の制限が 25Mb に増えました。(これまでは約5M)
  • ホームスクリーンWebAppは独自のストレージサンドボックスを持つようになりました。
    (追加する度に新しいストレージを持つようになったため、複数アプリの切り替えにはよいニュースです。Webサイトとホームの間でデータのやりとりをするには問題があります。)
  • ホームスクリーンWebAppのタイトルが定義できるようになりました。これまではサイトのページタイトルが使われていたのが、別名を定義できるようになりました。
また、apple-mobile-web-app-orientations という、WebAppの向きを指定できるメタタグもあるそうです。しかし、これはまだ動かないそうな。

WebView の更新

WebView の JavaScriptSafari の 3.3倍 遅い。しかし、これは SunSpider(ベンチマークツール)の結果に過ぎない。全ての機能をカバーしているわけではないし、トータル描画時間でもない。だから、WebView のアプリが 3.3倍 遅いという意味では無い。
他に幾つかよいニュースを発見しました。
  • WebAppのデバッグのためのリモート Web Inspector
  • 部分レンダリングを抑止する属性 supressesIncrementalRendering。
  • info.plist の WebKitStoreWebDataForBackup。localStorageやSQL databaseのiCloud等へのバックアップ。
  • 開発者契約の変更。(良いニュースなの??)

リモート デバッギング

初めて、 iOS 上の Safari に公式リモート Web Inspector が追加されました。これで iWebInspector や Weinre は過去の物となりました。このリモートデバッガーはシミュレータか、USBで繋がれた実機で動きます。(実機はUSBに繋がないといけない)
リモートインスペクションを始めるためには Safari 6 for Desktop が必要です。残念なことにサポートしているのは Mac だけです。Safari for Windows は 5.x で開発が止まり、もう利用出来ません。ですので、iOS デバイスのwebデバッグができるのは Mac OS だけです。
セキュリティの理由から、最初に Web Inspector を有効にする必要があります。「Safari」→「環境設定」→「詳細」から、「メニューバーに”開発”メニューを表示」をチェックします。
次の環境でデバッグが可能です。
  • iOSデバイス、またはシミュレータの Safari
  • iOSデバイス、またはシミュレータにインストールされた WebApp
  • Apache Cordova/PhoneGap のような WebView を使ったネイティブアプリ
ネイティブアプリは、Xcodeでインストールしたアプリだけインスペクできます。(つまり自分で開発したアプリ)そのため、Google Chrome のようなものはできません。
 
Safari 5 や ChromeWebkit Inspector を使っているなら、Xcode のネイティブ開発UIをベースにした Safari 6 の 完全に再デザインされたインスペクターを目にするでしょう。新しいUIを理解するまで迷うでしょう。 このインスペクターでできることは
  • HTML、CSS の確認とライブ変更
  • ストレージへのアクセス: クッキー、Local Storage、Session Storage、SQL Database。
  • webapp のプロファイル: ネットワークリクエスト、レイアウト&レンダリングJavaScript、イベントのパフォーマンスレポート。パフォーマンスツールの大きな進歩です。
  • DOMの検索
  • 全ての警告とエラーを一カ所で確認
  • worker thread の管理
  • JavaScript ブレークポイントの管理、キャッチしない例外のブレーク
  • コンソールへのアクセスとJavaScriptの実行
  • JavaScriptコードのデバッグ
  • 対象の要素をタッチしてインスペクトする
素晴らしいよApple! 私達はこれを長い間待っていた!!

その他の小さなアップデート

  • JavaScriptのパフォーマンスが 20%向上
  • Google Maps が iOS6 から使えなくなる。http://maps.google.com へのアクセスは ネイティブアプリではなく、GoogleMapsのWebサイトへリダイレクトされる。そこで、ネイティブマップアプリを開く新しいURLスキーマができた。maps:?=<query> queryはまさに検索文字列か、緯度経度をいれる。ルートナビゲーションを開始するパラメータは次のようになる。maps:?saddr=<source>&daddr=<destination>
  • XHR2: XMLHttpRequestProgressEvent をサポート
  • input の autocomplete を公式サポート
  • DOM4 の Mutation Observers を実装。WebKitMutationObserver で DOMの変更をキャッチできる。
  • -webkit-transform: preserve-3d でのハードウェアアクセラレーションの廃止。パフォーマンステクニックとしてこれを使うことは止めるべきだ。
  • window.selection による Selection API
  • <keygen> 要素
  • Canvas アップデート: createImageData の引数は1つになり、二つの関数が増えた。高解像度対応の、webkitGetImageDataHD と webkitPutImageDataHD。
  • SVGプロセッサとイベントの更新
  • 新しい CSS viewport が結びつけられた。 vh (viewport height), vw (viewport width) と、vmin(vw と vh の最小値)
  • CSS3 Exclusions と CSS Regions が β1で利用可能だったが、最終バージョンで削除された。
  • iCloud タブ。Mac、iPhoneiPadでタブを同期することが出来る。そのため同じURLが全てのデバイスへ配布される。モバイルWebのアーキテクチャに気をつける必要がある。
 

以上、 iPhone 5 and iOS 6 for HTML5 developers, a big step forward: web inspector, new APIs and more の紹介でした!あとちょっと、「まだ待っているもの」、「最後に」と続きますが、そこは割愛。気になる方は是非原文を読んで下さい。かなり意訳&はしょったところもありますので、ご指摘&コメント歓迎です。

個人的に今回の目玉はやはり リモートWebインスペクターに限りますね!特にプロファイラとブレークポイントが泣けるほど嬉しい!これを切望したWeb開発者も大勢いると思います。

これで開発環境も充実してきたし、ますますWebアプリが盛り上がっていくとおもしろいなー、と思う次第でありました。