JavaScriptでMetro スタイル アプリ開発
Windows 8からの新しい種類のアプリ「Metro スタイル アプリ」は、JavaScriptで作れます。前回 は、Visual BasicとC#でMetro スタイル アプリの地図アプリ開発について紹介しましたが、今回はJavaScriptでBing Mapsと連携したMetro スタイル アプリを開発してみましょう。
JavaScriptでBing Mapsを利用する場合は、この連載で何回も登場した、Bing Maps AJAX Control を利用します。Metro スタイル アプリの場合も、同様の機能が利用できますが、少し勝手が異なる部分もあります。それらも踏まえつつ、JavaScriptでのMetro スタイル アプリ開発を紹介していきます(図1 ) 。
図1 Windows 8 Metro スタイル アプリの開発
前回の繰り返しになりますが、Metro スタイル アプリの地図アプリ開発の紹介となりますので、Metro スタイル アプリの開発全般については、デベロッパー センターのMetro スタイル アプリ開発 も参照してください。
開発環境の準備
最初に開発環境を準備しましょう。開発は、Windows 8 Release Preview とVisual Studio 2012 RC で行います。
無償で提供されているVisual Studio Expressをインストールする場合は、Metro スタイル アプリ開発用の、Visual Studio Express 2012 RC for Windows 8 を選択します。早期リリースバージョンであるVisual Studio 2012 RCは、すべてのエディションが無償で使えます。
Bing Maps SDK
以前に紹介したBing Maps AJAX Controlでは、JavaScriptのライブラリをWebページからscriptタグで参照して利用していましたが、Metro スタイル アプリを開発する場合、Bing Maps SDKをあらかじめインストールします。現在、Bing Maps SDK for Metro style apps (RP) が提供されています。
Bing Maps SDK for metro style appsのダウンロードおよびインストールは、Visual Studioの「ツール」メニューの「拡張機能と更新」から行えます(図2 ) 。Webサイトからダウンロードしてインストールもできます。
図2 Bing Maps SDKのダウンロードとインストール
インストールを行うと、Visual Studioを再起動します。
Bing Maps Keyの取得
Bing Maps SDKの地図コントロールを使うには、これまでの連載と同じくBing Maps Key が必要です。Bing Maps Account Center にサインインしてBing Maps Keyを取得します。はじめて使う場合は、アカウントの登録が必要です(図3 ) 。また、Metro スタイル アプリの利用規約(Terms of User )は、これまでのBing Maps APIの利用規約とは別に用意されていますので注意してください。
図3 アカウントの登録
Bing Maps Keyは、メニューの「Create or view keys」から新しく作れます(図4 ) 。Application typeは、「 Metro style app (BETA)」を選びます。Submitボタンをクリックすると、新しくキーが生成され同じページにキーのリストが表示されます。
図4 Bing Maps Keyの作成
Metro スタイル アプリ プロジェクトの作成
それでは、Visual StudioでMetro スタイル アプリのプロジェクトを新規作成しましょう。Metro スタイル アプリは、C++、C#、Visual Basic、JavaScriptのどれでも開発できます。Bing Maps SDKを利用する場合も、どの言語でも開発できます。
今回は、JavaScriptを使います。メニューの「ファイル」ー「新しいプロジェクト」から、図5 のように「Windows Metro style」の「空のアプリケーション」を選択して、プロジェクトを作成します(図5 ) 。ここではアプリ名を「SampleMapAppJS」としました。
図5 プロジェクトの新規作成
Bing Maps SDKの参照
プロジェクトでBing Maps SDKを利用するため、プロジェクトからSDKを参照します。メニュー「プロジェクト」―「参照の追加」から、参照マネージャーを開きます。図6 のように、Windowsの拡張子にある「Bing Maps for JavaScript 1.0 (RP)」をチェックし、OKボタンをクリックして完了です。
図6 Bing Maps for JavaScriptの参照
以上で、地図アプリのためのプロジェクトができました。
地図の表示
ソリューションエクスプローラーを見てください(図7 ) 。default.htmlやdefault.css、default.jsなどのファイルがあり、アプリがHTMLやCSS、JavaScriptで構成されているのがわかります。default.htmlがアプリの画面になります。default.jsには、アプリがアクティブ化した時や中断時の処理が書かれています。
図7 ソリューションエクスプローラー
default.htmlのコードを見ると、既にいろいろとコードが書かれています。何も編集せずに、メニュー「デバッグ」―「デバッグ開始」からアプリを実行すると、bodyタグの中にあるテキストを表示するアプリが起動します。
default.htmlの編集
さて、地図を表示するようコードを編集していきましょう。default.htmlファイルを開きます。headタグの中に次のscriptタグを追加して、Bing Maps のライブラリを使えるようにします。
<script src = "ms-appx:///Bing.Maps.JavaScript//js/veapicore.js" ></script>
src属性を見てください。Bing Maps for JavaScriptライブラリは、アプリから利用するためパッケージ化されています。パッケージのリソースにアクセスするには、「 ms-appx://」プレフィックスを使います。
Bing Maps AJAX Controlのすべての機能を利用するには、さらにveapimodules.jsも参照します(今回の内容では必要ありません) 。
<script src = "ms-appx:///Bing.Maps.JavaScript//js/veapimodules.js" ></script>
続いて、地図コントロールを表示する場所を用意します。bodyタグの中を次のように置き換えます。
<body>
<div id = "map" style = " position : relative ; width : 100% ; height : 100% ; " ></div>
</body>
ここまでの内容は図8 のようになります。
図8 default.htmlの編集
地図コントロールの初期処理
次はJavaScriptの記述です。地図コントロールを利用するために必要な初期処理を行います。必要な作業とコードは、次の3つです。
1. Mapオブジェクトの変数の定義
var map ;
2. 必要なファイルの読み込み(Mapモジュールのロード)
Microsoft . Maps . loadModule ( 'Microsoft.Maps.Map' , { callback : initMap });
3. Mapオブジェクトの生成(初期化処理)
function initMap () {
var options =
{
credentials : 'BingMapsKey' ,
center : new Microsoft . Maps . Location ( 35.71 , 139.8107 ),
zoom : 8
};
map = new Microsoft . Maps . Map ( document . getElementById ( 'map' ), options );
}
Mapオブジェクトの生成は、Bing Maps AJAX Controlでは、必ず出てくるコードです。第13回 から第18回 で紹介しています。また、モジュールのロードも、AJAX Controlの機能です。スクリプトをモジュールとして登録し、必要になった時点でロードする機能です。連載では、第28回 で紹介しています。ここでは、既定で用意されている基本的なモジュールをロードし、ロード完了後initMap関数を呼ぶようにしています。
3つのコードを、jsフォルダーにあるdefault.jsファイルに追記していきます。default.jsファイルを開いてください。JavaScriptによるMetro スタイル アプリの一般的なコードが自動生成されています。
( function () {
"use strict" ;
})();
コードは、名前の競合などを避けるため、自己実行型の匿名関数で記述されています。また、JavaScriptのstrictモードを有効にする"use strict” が記述されています。これにより、より的確なエラーチェックが可能になります。
地図コントロールの初期処理を行うタイミングは、アプリがアクティブ化したときです。コード中のapp.onactiated 部分が、その場所です。コードでは、アクティブ時に、WinJS.UI.processAll メソッドを呼んでいます。このメソッドは、default.htmlファイルの中からJavaScript用Windowsライブラリ コントロール を探し、それらを初期化・描画します。
今はまだコントロールを追加していませんが、この後、アプリバーの追加のときに出てきます。ここでは、この処理が終わった後に、Mapモジュールをロードするコードを実行するよう記述します。done メソッドを用いて、次のように書くことができます。
args . setPromise ( WinJS . UI . processAll (). done (
function () {
Microsoft . Maps . loadModule ( 'Microsoft.Maps.Map' , { callback : initMap });
}));
そして、map変数の宣言は、WinJS.strictProcessing の行の後に、initMap関数は、app.start の前に追記します。default.jsの全体のコードを次に示します。
default.js
( function () {
"use strict" ;
var app = WinJS . Application ;
var activation = Windows . ApplicationModel . Activation ;
WinJS . strictProcessing ();
var map ;
app . onactivated = function ( args ) {
if ( args . detail . kind === activation . ActivationKind . launch ) {
if ( args . detail . previousExecutionState !== activation . ApplicationExecutionState . terminated ) {
} else {
}
args . setPromise ( WinJS . UI . processAll (). done (
function () {
Microsoft . Maps . loadModule ( 'Microsoft.Maps.Map' , { callback : initMap });
}));
}
};
app . oncheckpoint = function ( args ) {
};
function initMap () {
try {
var options =
{
credentials : 'BingMapsKey' ,
center : new Microsoft . Maps . Location ( 35.71 , 139.8107 ),
zoom : 8
};
map = new Microsoft . Maps . Map ( document . getElementById ( 'map' ), options );
}
catch ( e ) {
var md = new Windows . UI . Popups . MessageDialog ( e . message );
md . showAsync ();
}
}
app . start ();
})();
initMap関数内のBingMapsKeyは、取得したBing Maps Keyに置き換えてください。initMap関数は、try catchステートメントを追加しています。もし初期化時に例外が発生した場合は、ダイアログを表示するようにしています。
アプリの実行
ようやく、地図の表示ができるようになりました。ここまでを実行してみましょう。図9 のようにツールバーでローカルコンピューターを選択して、デバッグを開始します。
図9 デバッグの実行
アプリが起動して、画面全体に地図が表示されましたね。動作を確認したら、Visual Studioの画面に戻って、実行を停止します(メニュー「デバッグ」 -「 デバッグの停止」 ) 。
ここで、ローカルコンピューターのかわりにSimulatorを選択して実行すると、タブレットのシミュレーターで動作確認ができます(図10 ) 。右側にある各ボタンから、デバイスの解像度の変更や回転、経緯度の指定などが行えます。
図10 シミュレーターでのデバッグ
アプリの地図を見るとわかるように、左上に地図を操作するダッシュボードが表示され、Bing Maps AJAX Controlと同じであることがわかります。ダッシュボードは、初期化時に次のようにオプションを設定すると非表示にできます。
var options =
{
credentials : 'BingMapsKey' ,
center : new Microsoft . Maps . Location ( 35.71 , 139.8107 ),
zoom : 8 ,
showDashboard : false
};
位置情報を使った地図の操作
次は、デバイスのGPSなどのセンサーを利用して、位置情報を取得するプログラムを書いてみましょう。そして、取得した位置にプッシュピンを配置します。
プッシュピンの追加など、Bing Maps AJAX Controlの基本的な操作は、第13回 や、第14回 も参考にしてください。
アプリ マニフェストの編集
Metro スタイル アプリで位置情報を取得するには、あらかじめアプリ マニフェスト ファイルを編集し、アプリが位置情報を取得する機能があることを記述しておく必要があります。
アプリ マニフェストは、プロジェクトに含まれているpackage.appxmanifestファイルに、Windowsストアで公開する際に使うロゴ画像や、アプリが必要としている機能などが記述されています。ソリューションエクスプローラーから選択して開くと、マニフェスト デザイナーが開きます。
位置情報を取得する場合、「 機能」タブを開き、「 場所」をチェックします(図11 ) 。
図11 アプリ マニフェストの編集
位置情報の取得
Metro スタイル アプリでは、位置情報の取得にWindows APIにあるGeolocator クラスのgetGeopositionAsync メソッドを使います。経緯度は、結果のGeoposition オブジェクトのcoordinate.latitude プロパティとcoordinate.longitude プロパティからわかります。
Metro スタイル アプリでは、2種類のAPIが提供されています。ひとつは、Windows ランタイム と呼ばれ、Windowsの様々な機能にアクセスできます。Windows ランタイムは、Visual BasicやC#、C++からも同等の方法で利用できます。もうひとつは、JavaScript用Windows ライブラリ と呼ばれるCSSとJavaScriptのライブラリです。Geolocatorクラスは、Windows ランタイムで提供されています。
さて、位置を取得するコードは次のようになります。次のdisplayPosition関数をコードに追加してみましょう。追加する場所は、initMap関数の後です。
default.js
var loc ;
function displayPosition () {
if ( loc == null ) {
loc = new Windows . Devices . Geolocation . Geolocator ();
}
if ( loc != null ) {
loc . getGeopositionAsync (). then (
function ( pos ) {
var center = new Microsoft . Maps . Location ( pos . coordinate . latitude , pos . coordinate . longitude );
var pin = new Microsoft . Maps . Pushpin ( center );
map . entities . clear ();
map . entities . push ( pin );
map . setView ({
center : center ,
zoom : 15
});
},
function ( e ) {
var md = new Windows . UI . Popups . MessageDialog ( e . message );
md . showAsync ();
});
}
}
initMap関数内の最後にdisplayPositionを呼び出すコードを追記して動作を確認してください。
displayPosition ();
はじめてアプリを実行すると、図12 のように位置情報の取得の許可を求められます。ここでユーザーがブロックすると例外が発生し、情報はもちろん取得できません。
図12 位置情報の取得の確認ダイアログ
コード中のthen メソッドに着目してください。これはMetro スタイル アプリの非同期プログラミングで、一般的な記述方法です。位置情報の取得処理は、非同期で処理され、アプリの応答性を高めています。取得完了後の処理は、thenメソッドに指定すればよく、コードが示すように簡単に応答性の高いアプリを作れます。詳しくは、JavaScript での非同期プログラミング (Metro スタイル アプリ) などを参照すると良いでしょう。
W3C Geolocation APIの利用
位置情報の取得にWindowsランタイムのAPIではなく、W3C Geolocation API を利用して書くこともできます。
var nav ;
function displayPosition () {
if ( nav == null ) {
nav = window . navigator ;
}
var geoloc = nav . geolocation ;
if ( geoloc != null ) {
geoloc . getCurrentPosition (
function ( pos ) {
var center = new Microsoft . Maps . Location ( pos . coords . latitude , pos . coords . longitude );
var pin = new Microsoft . Maps . Pushpin ( center );
map . entities . clear ();
map . entities . push ( pin );
map . setView ({
center : center ,
zoom : 15
});
},
function ( e ) {
var md = new Windows . UI . Popups . MessageDialog ( e . message );
md . showAsync ();
}
);
}
}
このようにJavaScriptによるMetro スタイル アプリでは、HTML5などの知識も活用して開発ができます。
アプリ バーの追加
Metro スタイル アプリでは、コンテンツを操作するコマンドを表示する方法のひとつとして、アプリ
バー があります。Bing Maps SDKに直接かかわる内容ではありませんが、よりアプリらしくするため、アプリにアプリ バーを追加してみましょう。
図13 Windows 8の地図アプリのアプリ
バー
アプリ バーは、コンテンツのコマンドをオンデマンドで表示するために使います。既定ではアプリ バーは非表示です。画面の下から上へスワイプ動作で表示します。マウス操作の場合、右クリックで表示します。
作成済みのdisplayPosition関数を呼び出して、現在地を表示するボタンをアプリ バーに追加してみましょう。コマンドの動作は、今回は1個のボタンだけですが、ボタンの配置は、タッチで操作しやすいよう両端に配置します。コマンドが少ない場合や、永続的なコマンドは、右側に配置するようガイドラインで決められています。詳しくは、Metro スタイル アプリのコマンド実行の設計 を参照すると良いでしょう。
それでは、アプリにアプリ バーを追加します。アプリ バーなど、Metro スタイル
アプリ向けのコントロールは、JavaScript用Windowsライブラリ を利用します。
default.htmlのbodyタグの中に、次のコードを追加します。
default.html
<div data-win-control = "WinJS.UI.AppBar" data-win-options = "" >
<button data-win-control = "WinJS.UI.AppBarCommand"
data-win-options = "{id:'cmdMe',label:'現在地',icon:'home',section:'global',tooltip:''}" >
</button>
</div>
アプリ バーと、ボタンをひとつ追加しました。この状態でアプリを実行してみましょう。アプリの画面を右クリックすると、Metro スタイル アプリらしい丸枠の家のアイコンが表示されたかと思います(図14 ) 。
図14 アプリ バーのボタン
このように、Metro スタイル アプリ向けのコントロールは、divタグやbuttonタグを使い、data-win-control属性にWinJS.UI.AppBarなどコントロールの種類を指定します。また、コントロールのプロパティは、data-win-options属性に指定します。default.jsにある、WinJS.UI.processAllによって、default.htmlに指定したコントロールが初期化および描画されています。
イベントの登録
次は、ボタンをタップ(やクリック)したときのイベント処理を登録します。通常は、default.jsにイベント登録のコードを書きます。
イベントの登録も、地図コントロールの初期処理と同じ、アプリのアクティブ化したときに行うのが最適です。Mapモジュールをロードしているところに次のように追記します。
args . setPromise ( WinJS . UI . processAll (). done (
function () {
var button = document . getElementById ( "cmdMe" );
button . addEventListener ( "click" , displayPosition , false );
Microsoft . Maps . loadModule ( 'Microsoft.Maps.Map' , { callback : initMap });
}));
ボタンのclickイベントハンドラーとして、displayPosition関数を登録しています。以上で、ボタンのタップイベントと現在位置を表示する処理が結びつきました。アプリを実行して動作を確認してみましょう。意図したとおりに動いたでしょうか(initMap関数に追加したdisplayPositionは削除して試してください) 。
ボタンのアイコンの変更
アプリ バーのボタンには、定義済みのhomeアイコンを使いましたが、data-win-options属性のicon部分を「'url(/images/icon.png)'」や「''」のように画像や文字を指定できます。
また、Windows 8では、Segoe UI Symbolフォントにボタンに使えそうなアイコンが定義されています。スタート画面を表示しているとき、「 charmap」と入力して文字コード表を起動してください。
図15 文字コード表
文字コード表で、イラストの確認ができます(図15 ) 。ステータスバーに表示される「U+E114」などの値をicon部分に「''」のように変更すると、そのアイコンのボタンに変更できます。
アプリのライフサイクル
Metro スタイル アプリのライフサイクルについて紹介します。Metro スタイル アプリでは、これまでのWindowsアプリとは異なり、アプリは実行していない状態と実行している状態に加え、中断(サスペンド)の状態があります(図16 ) 。
図16 アプリのライフサイクル
中断状態はOSによって行われます。アプリが切り替わった時や、低電力状態に切り替わった時に、OSはアプリを中断状態にできます。
OSはいつでも、中断状態のアプリを実行していない状態、つまり、アプリを終了できます。これは、ほかのアプリへメモリの解放や、節電のために行われます。
終了するとアプリはメモリからアンロードされ、何もアプリでケアしていない場合はアプリが再アクティブ化した時、アプリは初期状態になってしまいます。
このため、Metro スタイル アプリでは、アプリの状態を保存し復元する処理を行う必要があります。アプリが中断状態になっとき、イベントが発生するので、このときに必要な処理をコーディングします。中断時にアプリの状態を保存して、復元できるようにしてみましょう。
アプリ状態の保存
JavaScript用Windowsライブラリには、アプリの一時的なデータ(セッションデータ)を格納する、WinJS.Application.sessionState オブジェクトが用意されています。セッションデータは、アプリがOSによって中断から終了した場合にのみ復元されます。
セッションデータを保存するタイミングは、中断状態になった時です。これは、default.jsにある、app.oncheckpoint イベントハンドラーで行います。今回のアプリの場合、経緯度とズームレベル、地図の種類をアプリの状態として保存します。コードを次のように編集します。
app . oncheckpoint = function ( args ) {
WinJS . Application . sessionState . center = map . getCenter ();
WinJS . Application . sessionState . zoom = map . getZoom ();
WinJS . Application . sessionState . mapTypeId = map . getMapTypeId ();
};
中断時の処理は以上です。
アプリ状態の復元
次は、アプリが再アクティブ化した時の処理を記述します。これは、app.onactivated イベントハンドラーで行います。今回の場合、onactivatedイベントハンドラー内で、Mapモジュールをロードし、initMap関数で地図の初期化を行っていますので、initMap関数を編集します。
復元方法も簡単です。自動的に終了した状態から再アクティブ化した場合、WinJS.Application.sessionStateに保存したデータが格納されていますので、これを使って地図を初期化します。次のようにinitMap関数内の該当部分を編集してください。
var state = WinJS . Application . sessionState ;
var center = state . center ;
var mapTypeId = state . mapTypeId ;
var zoom = state . zoom ;
var options =
{
credentials : 'BingMapsKey' ,
center : center || new Microsoft . Maps . Location ( 35.71 , 139.8107 ),
mapTypeId : mapTypeId || Microsoft . Maps . MapTypeId . road ,
zoom : zoom || 8 ,
showDashboard : false
};
map = new Microsoft . Maps . Map ( document . getElementById ( 'map' ), options );
これで、復元処理ができました。
アプリの中断から終了、復元をシミュレートするには、ツールバーの「中断」のドロップダウンリストから「中断とシャットダウン」をクリックします(図17 ) 。こうすると、中断と終了処理が行われ、次に実行したときにセッションデータを参照できます。
図17 中断とシャットダウン
アプリの状態が復元されるか確認してみてください。
おわりに
今回は、ここまでです。いかがでしたか。今回はJavaScriptを用いてBing Mapsと連携するMetro スタイル アプリを開発しました。Bing Maps AJAX Controlを利用しているため、これまでの知識も活用して地図アプリができました。
今回はあまり登場しませんでしたが、W3C Geolocation APIなど、一般的なWebアプリ開発の知識も活用して、Metro スタイル アプリの開発が可能です。既存のWebアプリを、Metro スタイル アプリへ移植も簡単にできるかも……しれません。
ただし、Metro スタイル アプリには、さまざまなUIや動作のガイドラインがあり、それらに従ったアプリが望まれます。また、Windowsストアで公開するため、審査に通る必要もあります。Metro スタイル アプリのガイドラインが、デベロッパーセンター に公開されていますので、少しずつ読み進めると良いかもしれませんね。