使ってみよう! Bing API/SDK

第18回使ってみよう! Bing Maps AJAX Control─⁠─Geolocation APIの利用

はじめに

2月10日、Internet Explorer 9 製品候補版が公開されました。この製品候補版では位置情報を取得するGeolocation APIの利用が可能になっています。今回はGeolocation APIとBing Maps AJAX Controlを連携してみましょう。また、Bing Maps AJAX Controlについては今回で一旦終了です。

Geolocation API は、Internet Explorer 9以外の主要なWebブラウザーでも利用できます。Geolocation APIや位置情報に関する内容は、gihyo.jp内に位置情報サービスのはじめ方という連載もありますので、こちらも参考になるかと思います。

余談ですが、Wi-FiのアクセスポイントやIPアドレスから位置情報を取得するサービスは、BingブランドではなくMSN Virtual Earthという名前で地図サービスが提供されていた2005年から提供されていました。一時期まではそのサービスを、Bing Mapsの前のバージョンにあたるLive Searchs Mapsで利用できていましたが、現在では終了しています。

Geolocation API

Geolocation APIは、W3Cで勧告候補の仕様で、このAPIを利用するとスクリプトから位置情報が取得できますGeolocation API Specification⁠。Geolocation APIで定義されているGeolocationオブジェクトには次のメソッドがあります。

  • getCurrentPosition:現在の位置情報を取得
  • watchPosition:定期的に位置情報を取得
  • clearWatch:定期的な位置情報の取得を終了

この中のgetCurrentPosition メソッドを使ってみましょう。JavaScriptで現在位置を取得する場合は、次のように記述します。

// 現在の位置情報を取得
window.navigator.geolocation.getCurrentPosition(successCallback, errorCallback);

function successCallback(position) {
    // 取得に成功した場合、経緯度を表示
    alert("Location: " + position.coords.latitude + ", " + position.coords.longitude);
}

function errorCallback(error) {
    // 取得に失敗した場合、エラーコードを表示
    alert("Error code: " + error.code);
}

取得に成功した場合、getCurrentPositionメソッドの第1引数に指定した関数にPositionオブジェクトが渡されます。経緯度は、PositionオブジェクトのcoordsプロパティCoordinatesオブジェクト)からさらに、latitudelongitudeプロパティから得ます。ここでは説明しませんが、このような呼出し以外にも、キャッシュされた位置情報の許容時間の指定なども可能です。

現在位置の表示

それでは、Bing Maps AJAX Controlで現在位置を表示してみましょう。まず、地図を表示するコードはこれまでと同じように次のようになります。jQueryのライブラリーの参照など、後ほど使用するためコードも一部含まれています。

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Bing Maps Sample</title>
    <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.4.4.js" type="text/javascript"></script>
    <script type="text/javascript" src="https://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&amp;ssl=1"></script>
    <script type="text/javascript">
        <!--
        var map = null;
        var bingMapsKey = "BingMapsKey";
        var position = null;

        function GetMap() {
            map = new Microsoft.Maps.Map(document.getElementById("map"), {credentials: bingMapsKey});
        }
        //-->
    </script>
</head>
<body onload="GetMap();">
    <div id="map" style="position: relative; width: 512px; height: 512px"></div>
    <div id="share"></div>
</body>
</html>

位置情報の取得に成功した場合、その地点にプッシュピンを追加するコードを追記しましょう。まず、<body>要素に現在位置の取得処理を呼び出すボタンを追加します。

<input type="button" value="Locate Me!" onclick="locateMe();" />

続いてJavaScriptのコードです。次のコードは現在位置の取得の要求部分です。

function locateMe() {
    if (window.navigator != null && 
        window.navigator.geolocation != null) {
        window.navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
    } else {
        alert("Geolocation not supported");
    }
}

現在位置の取得に成功した場合は、次のように記述します。Geolocation APIとの連携部分は、PositionオブジェクトからBing Maps AJAX ControlのLocationオブジェクトに変換するだけですので、特に難しいところはありませんね。

function successCallback(p)
{
    position = p;

    // Position オブジェクトから Location オブジェクト作成
    var loc = new Microsoft.Maps.Location(p.coords.latitude, p.coords.longitude);

    // 地図上の Entity オブジェクト削除
    map.entities.clear();

    // プッシュピンの表示
    var pin = new Microsoft.Maps.Pushpin(loc);
    map.entities.push(pin);
    
    // 結果の場所へ移動
    map.setView({center: loc, zoom: 12});
}

最後に、取得に失敗した場合です。関数に渡されるPositionErrorオブジェクトには次の3種類のエラー内容が定義されています。

function errorCallback(error) {
    var message = "";

    switch (error.code) {
        case error.PERMISSION_DENIED:
            // 位置情報へのアクセスをユーザーが拒否した
            message = "Permission denied";
            break;
        case error.POSITION_UNAVAILABLE:
            // 位置を特定できなかった
            message = "Position unavailable";
            break;
        case error.TIMEOUT:
            // 取得が許容時間内に完了しなかった
            message = "timeout";
            break;
    }
    alert(message);
}

以上で、現在位置を取得して地図上にプッシュピンを表示するところまでできました。実際に実行して確認してみてください。Internet Explorer 9では、図1のように通知バーが表示されます。許可すると位置情報が利用できる場合、その地点にプッシュピンが表示されます。

図1 位置情報取得の要求
図1 位置情報取得の要求

精度の表示

現在位置の表示は、実際とはかなり異なった結果だったかもしれません。これはIPアドレスなどからの推測のためしかたありません。Geolocation APIでは位置情報の精度も取得できます。この情報も地図上に表示するよう変更してみましょう。

Coordinatesオブジェクトのaccuracyプロパティを参照すると、経緯度の精度がメートル単位で取得できます。この値を半径、取得した経緯度を中心とした円を地図に描きます。領域を表すにはBing Maps AJAX ControlのPolygonクラスを使用します。

Polygonオブジェクトを作成するには円周上の経緯度を求める必要があります。中心の経緯度とメートル単位の半径から円周上の経緯度を求める計算は複雑なため、Movable Type Ltdで公開されているコードを使用します。このスクリプトを参照し、destVincenty関数が呼び出せる状態にしてください。

経度・緯度・精度からPolygonを地図上に表示するコードは次のようになります。

function displayPolygon(lat, lon, meters){
    // Movable Type Ltd の コードを使用して円周上の経緯度を得る
    var verticies = new Array();
    for (var d = 0; d <= 360; d+=3) {
        var result = destVincenty(lat, lon, d, meters);
        var loc = new Microsoft.Maps.Location(result.lat, result.lon);
        verticies.push(loc);
    }
    
    // Polygon の表示
    var color1 = new Microsoft.Maps.Color(25, 0, 163, 239);
    var color2 = new Microsoft.Maps.Color(150, 0, 163, 239);
    var polygon = new Microsoft.Maps.Polygon(verticies, { fillColor: color1, strokeColor: color2 });
    map.entities.push(polygon);
}

上記のdisplayPolygon関数の呼び出しを、successCallback関数内のプッシュピン表示前に追加しましょう。

displayPolygon(p.coords.latitude, p.coords.longitude, p.coords.accuracy);

実行結果は図2のようになります。

図2 精度の表示
図2 精度の表示

実はここまでの内容は、Internet Explorer 9 Platform Previewや、HTML5などのデモを公開しているWebサイト、Internet Explorer Test DriveにあるGeolocationデモ図3とほぼ同じものを作成していました。

図3 Geolocation デモ
図3 Geolocation デモ

作成したアプリケーションは、Geolocation APIが実装されているGoogle ChromeなどのWebブラウザーでも動作します図4⁠。Webブラウザー内部で位置取得のために使用しているサービスが、Internet ExplorerとGoogle Chrome・Firefox・Operaとでは異なるため、結果も異なっています。

図4 Google Chromeでの実行結果
図4 Google Chromeでの実行結果

ソーシャルネットワークサービスとの連携

現在位置を取得するユースケースとして、ソーシャルネットワーク アプリケーションでユーザーの更新情報に利用するといったことがあるかと思います。次はBing Maps AJAX Controlとは直接関係ありませんが、Bing Maps REST Servicesなどを利用して、ソーシャルネットワーク機能を追加します。

Messenger Connect Sharing badge

今回利用するのは、Messenger Connect Sharing badgeです。Sharing badgeを利用すると、Webサイトや写真などをLive MessengerなどのWindows Liveサービス上の友人や知り合いと共有できます。

Sharing badgeは図5のようなWebサイトに貼り付けるボタンです。ユーザーがクリックすると、指定されたWebサイトなどを共有できます図6⁠。

図5 Messenger Connect Sharing badge
図5 Messenger Connect Sharing badge
図6 Webサイトの共有
図6 Webサイトの共有

共有した内容は、live.comの更新情報や、Live Messengerの表示メッセージと更新情報図7⁠、Messenger Companionで使用されます。また、ユーザーがFacebookなどのサービスとWindows Liveサービスを接続していた場合、接続先のサービスにも反映されます図8⁠。

図7 Live Messenger 表示メッセージと更新情報
図7 Live Messenger 表示メッセージと更新情報
図8 Facebookとの連携
図8 Facebookとの連携

Sharing badgeの作成

このSharing badgeを利用して、現在位置を共有できるようにしましょう。リンク先を次のようなURLにするだけで、簡単に共有できます。このほかにもパラメーターを指定できますが、ここでは説明しません。

  • http://profile.live.com/badge/?
      url=共有するWebサイトのURL&
      title=タイトル&
      screenshot=サムネイルのURL

今回は、WebサイトのURLには、Bing Mapsで現在地を表示できるよう指定します。また、Bing Maps REST ServicesのLocation APIで現在地の住所を取得してタイトルに使用し、Imagery APIで地図画像を作成してサムネイルに指定します。Location APIとImagery APIについては、第9回第10回に紹介していてますので、併せて参照してください。

Location APIによる逆ジオコーディング部分は次のようになります。

function share() {
    map.getCredentials(createGeocodeRequest);
}

function createGeocodeRequest(credentials) {
    if (credentials === null) {
        alert("Credentials is null.");
        return;
    }

    $.ajax({
        type: "GET",
        url: "https://dev.virtualearth.net/REST/v1/Locations/" + 
            position.coords.latitude + "," + 
            position.coords.longitude,
        dataType: "jsonp",
        data: {
            key: credentials,
            c: "ja-JP",
            o: "json"
        },
        jsonp: "jsonp",
        success: function (data, dataType) {
            geocodeCallback(data);
        }
    });
}

function geocodeCallback(response) {
    if (response && response.errorDetails) {
        var text = "";
        $.each(response.errorDetails, function () {
            text += this + "\n";
        });
        alert(text); // error!
        return false;
    }

    if (response &&
        response.resourceSets &&
        response.resourceSets.length > 0 &&
        response.resourceSets[0].resources &&
        response.resourceSets[0].resources.length > 0) {

        var addr = response.resourceSets[0].resources[0].name; // 住所
        createBadge(position.coords.latitude, position.coords.longitude, addr);

    } else {
        alert("No result.");
    }
}

Sharing badgeをWebページに追加する部分は次のようになります。この中で、Imagery APIを利用した地図画像のURLも作成しています。

function createBadge(lat, lon, addr) {
    var url = "http://profile.live.com/badge/?" +
    "url=" + encodeURIComponent("http://bing.jp/map/?q=" + lat + "," + lon) +
    "&title=" + encodeURIComponent("現在地 " + addr) +
    "&screenshot=" + encodeURIComponent("http://dev.virtualearth.net/REST/v1/Imagery/Map/Road/" + lat + "," + lon + "/12?&pp=" + lat + "," + lon + ";35&ms=128,128&key=" + bingMapsKey);
    
    var badge = '<a title="Share with Messenger"><img style="border-style:none; vertical-align:middle; margin-right:4px" src="http://js.live.net/static/img/SharingBadge22x22Orange.png" alt="Share with Messenger" />共有</a>';
    $("#share").html(badge).find("a").attr("href", url);
}

最後に、作成したshare関数をsuccessCallback関数内で呼び出すようにすれば完成です。現在位置を取得すると、WebページにSharing badgeが現れます。ボタンをクリックすると図9のような画面になります。

図9 現在地の共有
図9 現在地の共有

おわりに

今回の内容は以上です。Bing Maps AJAX Controlとその他のWebサービスを連携して簡単なアプリケーションを作成してみました。いかがでしたでしょうか。今回でBing Maps AJAX Controlの紹介は一区切りです。

Bing Maps AJAX Controlはこれまでの連載からもわかるようにシンプルなライブラリーです。その機能については前回までの内容で概ね紹介していますが、各クラスの持つすべてのプロパティやメソッドの内容などについてはMSDN Libraryの参照をお願いします。

Bing Maps AJAX Controlを実際に使用してみると、Bird’s eye(概観図)やスムーズな動作など、注目する点があるのではないでしょうか。それらの点を活かして、ほかのライブラリーやWebサービスともうまく組み合わせて利用してみるとよいのではないかと思います。

また、この連載中にiPhoneだけでなくAndroid 2.xのブラウザーにも対応されています。モバイルアプリケーションにもぜひ活用してみてください。

おすすめ記事

記事・ニュース一覧