ケーススタディ - HTML5 MathBoard

はじめに

MathBoard アプリケーション

iPad 版 MathBoard は、PalaSoftware のアプリで、洗練されたアプリです。繊細で自然なアニメーションが多数あり、独自のリアルな外観と操作感があります。目標は、iPad アプリケーションを HTML5 に忠実に移植することでした。

N2N-Apps は、HTML5 テクノロジーによる次世代のウェブおよびモバイル アプリケーションの構築に重点を置くソフトウェア開発会社です。同社は 2010 年に Jeremy Chone によって設立されました。Jeremy は Netscape、Oracle、Adobe で 11 年間エンジニアリングと管理の経験を積んだ後、高品質のウェブアプリとモバイルアプリを構築するために、その専門知識を企業と共有することにしました。N2N-Apps は、品質と配信速度に重点を置いています。

Chrome ウェブストアで MathBoard をダウンロードする Chrome ウェブストアで MathBoard をダウンロードする(無料版)

要件

この HTML5 移植プロジェクトの主な要件は次のとおりです。

  1. 元の iPad アプリの外観とユーザー インターフェースを忠実に再現したポート。
  2. 対象のフォーム ファクタ(キーボード/マウスを備えた PC/Mac とタッチスクリーンなど)に合わせて調整します。
  3. 該当する機能の 100% を実装する。
  4. 主に HTML5 ブラウザをターゲットにします。
  5. アプリケーションを「サーバーレス」にして、アプリケーションが完全にクライアント上で実行され、静的サーバーまたは Google Chrome パッケージ化されたアプリケーションでホストされるようにします。
  6. 問題解決機能以外のすべての機能を備えた 1.0 バージョンを 1 か月以内に作成します。

アーキテクチャ

アーキテクチャ

要件に基づいて、次のアーキテクチャを選択しました。

  1. HTML5: HTML4 のサポート要件がないため、HTML5 をベースとすることにしました。
  2. jQuery: HTML5 には jQuery を優れたものにする高度なセレクタが多数ありますが、DOM と関連イベントを操作するための非常に堅牢で成熟した方法が jQuery に備わっているため、jQuery を採用することにしました。また、jQuery は DOM 中心であるため、アプリケーションの設計と実装が HTML に近づく傾向があります。
  3. SnowUI: jQuery には、DOM を操作するための優れた API とベスト プラクティスが用意されていますが、HTML5 MathBoard アプリケーションでは、さまざまなビューをオーケストレートするための MVC または MVP スタイルのフレームワークが必要でした。SnowUI は、jQuery 上に構築されたシンプルで強力な MVC フレームワークです。DOM 中心の MVC メカニズムと、カスタム コンポーネントを柔軟に構築する方法を提供します。また、アプリケーション デベロッパーが最適と思われるウィジェット/コントロール ライブラリやカスタムコードを使用することもできます。

iPad から PC への移行に関する考慮事項

PC 用にアプリケーションを HTML5 に移植する際には、アプリケーションのデザインとユーザー操作にいくつかの変更を加える必要がありました。

画面の向き

iPad の MathBoard は縦向き専用であるため、通常は横向きで使用される PC ディスプレイには最適ではありませんでした。そのため、UI デザインを再編成し、設定パネルを右側のスライディング ビュー(CSS3 遷移によるアニメーション)に移動しました。

画面の向き
iPad と HTML5 の画面の向き

入力: キーボード/マウスとタップ

iPad 版とウェブ版のもう一つの大きな違いは、入力インターフェースです。iPad ではタッチ インターフェースのみですが、PC ではマウスとキーボードの両方を考慮する必要があります。

iPad の MathBoard 入力コントロールは非常に洗練されています。ウェブ インターフェースでも同じ忠実度の高い表現を実現したいと考えました。解決策として、キーボード ショートカットのサポートを追加し、CSS の配置を使用して UI コントロールを複製しました。HTML5 への移植はピクセル単位で完璧でした。

UI コントロール
iPad と HTML5 のバージョン設定

iPad のインターフェースと同様に、ユーザーは左右矢印をクリックしてコントロールの値を変更できます。縦線をドラッグして値をすばやく変更することもできます。clickkeydown に繰り返し動作が実装され、ユーザーがマウスまたはキーボードを押すと値の変更を高速化できるようになりました。

TAB キーによる入力フィールド間の移動と、← キーと → キーによる値の切り替えがサポートされました。

iPad 版の機能で、PC インターフェースではあまり意味がなかったのが描画ボードです。実装は簡単ですが、マウスで数字を描画するのは現実的ではありません。代わりに、描画ボードの実装よりもキーボード インターフェースの調整に多くの時間を費やすことにしました。

HTML5 の機能

ウェブ版 MathBoard では、次のような多くの HTML5 機能を使用しています。

ローカル ストレージ

MathBoard では、ユーザーがクイズを保存して後で再生できます。HTML5 MathBoard は、SnowUI DAO インターフェースを使用して HTML5 localStorage を使用してこの機能を実装します。

データが十分にシンプルで、高度なインデックス登録を必要としないため、localStorage が自然な選択肢でした。すべてのクイズは、テキストとして JSON.stringify する 1 つの JSON 形式で保存されます。

snowUI DAO はシンプルな CRUD インターフェース ラッパーであり、UI がデータの実際の保存方法を気にすることなくデータを取得できるようにします。DAO の実装はストレージの詳細を処理します。

MathBoard では、ストレージ要件は非常にシンプルでした。ユーザー設定とクイズデータのみを保存する必要がありました。どちらも localStorage に JSON 文字列として保存されていました。

たとえば、設定値の DAO は次のようになります。

snow.dm.registerDao('settingValue', (function() {

  var _settingValues = null;

  function SettingValueDao() {};

  // ------ DAO CRUD Interface ------ //
  // get
  SettingValueDao.prototype.get = function(objectType, id) {
    return $.extend({},getSettingValues()[id]);
  };

  // find, remove

  // save
  SettingValueDao.prototype.save = function(objectType, data) {
    var storeValue = getSettingValues('settingValue')[data.id];
    if (!storeValue) {
      storeValue = {};
      getSettingValues()[data.id] = storeValue;
    }

    $.extend(storeValue, data);
    saveSettingValues();
  };
  // ------ /DAO CRUD Interface ------ //

  function getSettingValues() {
    if (_settingValues == null) {
      var settingValuesString = localStorage.getItem('settingValues');
      if (settingValuesString) {
        _settingValues = JSON.parse(settingValuesString);
      } else{
        _settingValues = {};
      }
    }

    return _settingValues;
  }

  function saveSettingValues(){
    var settingValues = getSettingValues();
    if (settingValues != null) {
      localStorage.removeItem('settingValues');
      localStorage.setItem('settingValues', JSON.stringify(settingValues)); 
    }
  }

  return new SettingValueDao();
})());

この DAO が settingValue に登録されると、UI はストア ロジックを気にすることなく、次の呼び出しを行うことができます。

var addition = snow.dm.get('settingValue', 'operator_addition');
addition.value = true; // to check the addition checkbox
snow.dm.save('settingValue', addition);

CSS3 フォント

MathBoard はカスタム フォントを使用します。CSS3 フォント サポートのおかげで、アプリに「Chalkduster」TrueType フォントを簡単に含めることができました。

@font-face {
  font-family: Chalkduster;
  src: url(Chalkduster.ttf);
}

このフォントはアプリ内のほとんどのテキストのデフォルトだったため、本文のデフォルトにしました。

body {
  background: #333333;
  font-family: Chalkduster;
  color: #ffffff;
}

CSS3 グラデーション、シャドウ、角の丸め

グラデーション、シャドウ、透明度、角の丸めはすべて CSS3 で作成されています。これは、従来の .png によるユーザー インターフェースの作成方法と比べて、本当に助かりました。

また、高度な CSS3 プロパティを使用して、スクロールバーの外観をカスタマイズし、より目立たないようにしました(WebKit ブラウザでスクロールバーのスタイル設定を行うには、http://webkit.org/blog/363/styling-scrollbars/ をご覧ください)。

CSS3 遷移

HTML5 MathBoard では、iPad のアニメーションをすべて再現し、右側のパネルのスライドに新しいアニメーションを追加しました。CSS3 の遷移により、アニメーションを簡単に追加でき、最高のパフォーマンスを実現できました。

アプリには主に 3 つのアニメーションがありました。

1)スライドする右側のペイン

最初のアニメーションは右ペイン(#rightPane)にあり、ユーザーが新しいクイズを開始するとスライドして閉じ、ユーザーがクイズを終了するとスライドして開きます。この効果を作成するには、次の CSS 遷移を使用し、JavaScript でトリガーしました。rightPane のデフォルト スタイルが開いています。

#rightPane {
  /* look and feel, and layout property */
  position: absolute;
  width: 370px;
  height: 598px;
  top: 28px;
  left: 720px; /* open */
  -webkit-transition: all .6s ease-in-out;
}

ユーザーがクイズを開始すると、JavaScript ロジックによってパネルが移動します。

var $rightPane = $('#rightPane');
var left = $rightPane.position().left - 400;
setTimeout(function() {
  $rightPane.css('left', left + 'px');
}, 0);

この実装に関する注意事項は次のとおりです。

  1. アプリのサイズが固定されている場合は、CSS クラス「.close」を使用して、開く位置をハードコードするのと同じ方法で閉じる位置をハードコードすることもできます。
  2. CSS の「translate」を使用することもできます。これは、ペインの「left」プロパティをアニメーション化するよりもパフォーマンスが優れています。これは、3D 変換がハードウェア アクセラレーションされているモバイル デバイス(iOS など)で特に当てはまります。
  3. この場合、元の位置は変更前に設定されているため、setTimeout は厳密には必要ありません。ただし、rightPane をスライドインする直前にクイズを表示することで、ブラウザでアニメーションをスムーズにできます。

2)設定ダイアログ ボックスのアニメーション

ユーザーが右側の設定をクリックすると、設定ダイアログが画面の下部から表示され、適切なセクションまでスクロールします。

そのため、右側のペインにも同様の遷移を追加しました。時間がかかったのは、ダイアログが最初に表示された際のぎくしゃくした動作を解決することだけでした。ダイアログ UI をキャッシュに保存するようブラウザに指示するため、ダイアログを 1 回表示してスクロールするようにしました。最初は display: none で試しました。このアプローチは間違っていました。ブラウザは、ダイアログを表示する必要がないことを前提としていたためです。解決策として、初期化時に z-index: -1 で設定を表示し、ユーザーには見えないようにしつつ、ブラウザには表示するようにしました。

3)クイズの成功または不正なメッセージのアニメーション

3 つ目のアニメーションは、実際には 2 つに分かれています。[成功] または [不正確] メッセージが表示されたら、まず 1 つの点にスケーリングし、少し待ってからさらに大きくスケーリングして消えます。これには、2 つの CSS3 アニメーション スタイルがあり、webkitTransitionEnd イベントで JavaScript を介してオーケストレートします。

.quiz-result > div.anim1 {
  opacity: 0.8;
  -webkit-transform: scale(6,6);
}
.quiz-result > div.anim2{
  opacity: 0;
  -webkit-transform: scale(9,9);
}
setTimeout(function() {
  $msg.addClass("anim1");
  $msg.bind("webkitTransitionEnd", function(){
    if ($msg.hasClass("anim1")) {
      setTimeout(function() {
        $msg.removeClass("anim1");
        $msg.addClass("anim2");
      }, 300);
    } else {
      $msg.remove();
      displayNextItem();
      freezeInput = false;
    }
  });
}, 0);

オーディオタグ

ユーザーがクイズに回答すると、アプリが成功または失敗のサウンドを鳴らします。簡単な方法としては、音声タグを使用して play() を呼び出す方法があります。これらの音声ビットは、アプリのメインページに追加されます。

<audio id="audioCorrect" src="correct.mp3" preload="auto" autobuffer></audio>
<audio id="audioWrong" src="wrong.mp3" preload="auto" autobuffer></audio>

まとめ

HTML5 は、新しいタイプのウェブ、デスクトップ、モバイルアプリを実現しています。CSS3 は、アプリの外観と操作感を iPad 版 MathBoard の高度な洗練さに近づけるために役立ちました。HTML5 ストレージはデータの永続性に最適で、HTML5 音声のシンプルさにより、iPad アプリを忠実に再現できました。