はじめに
YOLPことYahoo! Open Local Platform Hacks 第2回です。今回は具体的なAPIの使い方について少し詳しく見てみましょう。イメージが掴みやすいように具体的なシナリオを挙げ、実際に動作するサンプルの実装を題材としてYOLPの使い方や組み込み方を紹介していきたいと思います。
今回は
- 現在位置を地図に表示し続ける
- 地図をなぞって距離を測定する
の2つのシナリオについて説明します。
現在位置を地図に表示し続ける
現在のスマートフォンはほとんどが位置情報取得の機能を備えており、JavaScriptからGeolocation APIとして利用することができます。
以下はwatchPosition()で継続的に位置を取得するサンプルです。iPhoneなどで表示してみてください。右上の「start watchPosition」ボタンを押すと、地図を現在位置に移動し、測位精度に応じた円を地図上に描画します。
なお<あなたのアプリケーションID>の部分はご自分で取得されたアプリケーションIDに書き換えてお試しください。
<!DOCTYPE html> <html lang="ja"> <head> <title>geolocation x YOLP sample</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=no"> <style type="text/css"> body{ margin:0; padding:0; } </style> </head> <body> <div style="width:320px; height:320px; position:relative;"> <div id="map" style="width:320px; height:320px;"></div> <button id="location" style="position:absolute; top:8px; right:8px; z-index:3; display:none;">start watchPosition</button> </div> <script type="text/javascript" src="http://js.api.olp.yahooapis.jp/OpenLocalPlatform/V1/jsapi?appid=<あなたのアプリケーションID>"></script> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script type="text/javascript"> $(document).ready(function($){ var map = new Y.Map("map"), circle = new Y.Circle(new Y.LatLng(0,0), new Y.Size(0,0), {unit:"km", strokeStyle:new Y.Style("99cc99", 2, 0.7), fillStyle:new Y.Style("99cc99", 1, 0.2)}), geo = navigator.geolocation, wid = "", button = $('#location'), Start = function(){ button.html('stop watchPosition'); wid = geo.watchPosition(function(pos){ var lat = pos.coords.latitude, lon = pos.coords.longitude, ll = new Y.LatLng(lat,lon), acc = parseInt(pos.coords.accuracy, 10) / 1000; circle.latlng = ll; circle.radius = new Y.Size(acc, acc); circle.adjust(); map.panTo(ll, true); }); }, Stop = function(){ geo.clearWatch(wid); wid = ""; button.html('start watchPosition'); }; if(geo){ button.bind("click", function(){ if(wid) Stop(); else Start(); }).show(); } map.drawMap(new Y.LatLng(35.691052, 139.701258), 14, Y.LayerSetId.NORMAL); map.addFeature(circle); }); </script> </body> </html>
navigator.geolocation
Geolocation APIはnavigator.geolocationオブジェクトから利用します。navigator.geolocationが定義されていればGeolocation APIが利用可能です。
var geo = navigator.geolocation; if(geo){ //do something with geo }
watchPosition()
navigator.geolocationには現在位置を取得するgetCurrentPosition()と現在位置を監視し続けるwatchPosition()の2つのメソッドがあります。ここではwatchPosition()を使っています。
watchPosition()の引数には、成功時コールバック、エラー時コールバック、オプションの3つを渡せます。今回は成功時コールバックしか渡していません。
コールバックには取得した位置情報を格納したオブジェクトが渡されます。主に利用するのは以下の3つの値です。
- obj.coords.latitude (測位位置の緯度)
- obj.coords.longitude (測位位置の経度)
- obj.coords.accuracy (メートル単位での測位精度)
この3つの情報を使うことで、測位位置とその精度範囲を示す円を描画できます。
円の描画
円を描画するには、Y.Cicleオブジェクトを生成し、Y.MapオブジェクトにaddFeatureします。Y.Cicleの生成には中心位置の緯度経度、半径、オプションを引数として渡します。どうせ後から更新するので、位置や半径はダミーで0を渡しています。
ポイントはオプションの「unit」です。デフォルトでは半径の値はピクセル値の設定なので、例えば縮尺を変えても円の半径は同じ大きさです。今回は円の半径は実距離に合わせたいのでこれでは困ります。そこでunitに"km"を指定することで、半径の値をキロメートル単位の実距離として扱ってくれ、縮尺変更時などにも自動的に再計算と再描画をしてくれるようになります。
なお、Y.Circleは厳密には円ではなく楕円なので、radiusを指定するときにはY.Sizeオブジェクトとして指定します。
var map = new Y.Map("map"); var circle = new Y.Circle(new Y.LatLng(0,0), new Y.Size(0,0), { unit:"km", strokeStyle:new Y.Style("99cc99", 2, 0.7), fillStyle:new Y.Style("99cc99", 1, 0.2) }); map.drawMap(new Y.LatLng(35.691052, 139.701258), 14, Y.LayerSetId.NORMAL); map.addFeature(circle);
円の更新
これらを用いて、watchPosition()で新しい位置と精度が得られるたびに円を更新し、地図をその場所に移動します。Y.Circleは生成後に中心位置(latlng)と半径(radius)を変更することができます。変更後、adjust()メソッドを呼ぶことで円が再描画されます。
なおwatchPosition()の引数のpos.coords.accuracyはメートル単位の値が入っているので、Y.Circleの半径指定単位に合わせてキロメートル単位に変換しておきます。
navigator.geolocation.watchPosition(function(pos){ var lat = pos.coords.latitude, lon = pos.coords.longitude, ll = new Y.LatLng(lat,lon), acc = parseInt(pos.coords.accuracy, 10) / 1000; circle.latlng = ll; circle.radius = new Y.Size(acc, acc); circle.adjust(); map.panTo(ll, true); });
まとめ
このサンプルには、
- navigator.geolocationのコールバックで緯度経度や精度情報を利用する方法
- YOLPで円を描画する方法
- 円の半径を実距離で指定する方法
- 一度描画した円の大きさや位置を変える方法
などが含まれています。