使ってみよう! Bing API/SDK

第26回地図データ用クラウドデータベースと作るWebアプリ

はじめに

今回は、Bing Spatial Data Servicesを利用して簡単なアプリを作ってみましょう。Bing Spatial Data Servicesを利用すると、位置情報を扱うクラウドデータベースをREST APIで利用できます。前回Data Source Management APIを利用して、Data Sourceの作成とQuery APIによる位置情報を条件とした検索を紹介しました。これらに加えて、地図コントロールのBing Maps AJAX Controlと連携したアプリを作ります。

作成するアプリは、全国のガソリンスタンド(とその他の燃料給油所・販売店)の場所を示すアプリです図1⁠。位置情報のデータは、Bing Spatial Data Servicesを利用してクラウド上に置いて、表示されている範囲のデータを取得します。

図1 ガソリンスタンド アプリ(1)
図1 ガソリンスタンド アプリ(1)
図2 ガソリンスタンド アプリ(2)
図2 ガソリンスタンド アプリ(2)

アプリはJavaScriptを使用して作成します。jQueryも利用しています。

また、おまけとしてガソリンスタンドの分布をヒートマップ表示図3する方法も紹介します。

図3 ヒートマップ
図3 ヒートマップ

データの準備

Data Sourceとなるデータを準備します。今回は、国土交通省の国土数値情報ダウンロードサービスで提供されているデータを利用します。利用したデータは、JPGIS準拠データにある燃料給油所データです。

データの内容は、次の3種類です。

  • 燃料給油所の位置(経緯度)
  • 燃料給油所の所在地
  • 店舗分類を表すコード

店舗分類コードは、①自動車用の燃料を販売するSS(サービスステーション)のガソリンスタンドと、②LPガススタンド、③家庭で使用する灯油等の燃料販売店の3種類です。

実際にアプリを作成するとなると、店舗名やガソリンの価格情報などもほしいですね。今回は利用できる情報がありませんので、これらの情報のみでData Sourceを作成します。

Data Sourceの定義

作成するData Sourceのプロパティは次のように定義します。

名前データ型説明
IDEdm.StringID
LatitudeEdm.Double緯度
LongitudeEdm.Double経度
AddressEdm.String燃料給油所の所在地
CodeEdm.Int64店舗分類コード

店舗分類コードを含めて、ガソリンスタンドだけでなく、LPガススタンドやその他の燃料給油所の情報もまとめたData Sourceにします。

アップロード用のファイルは、前回と同じくテキストファイルとして作成します。よって、テキストファイルの最初の2行は次のようになります。エンティティの種類の名前は、FuelStoresとしました。

Bing Spatial Data Services, 1.0, FuelStores
ID(Edm.String,primaryKey)|Latitude(Edm.Double)|Longitude(Edm.Double)|Address(Edm.String)|Code(Edm.Int64)

データの変換

さて、提供されているデータはXML形式のファイルで、都道府県ごとに分かれています。すべてのファイルをダウンロードしてData Sourceとしてアップロードできるよう変換しましょう。ダウンロードしたデータは、次のようなXML形式のデータになっています。

燃料給油所の位置の情報部分
<jps:GM_Point id="n00597">
    <jps:GM_Point.position>
        <jps:DirectPosition>
            <DirectPosition.coordinate>35.23375805 136.82025784</DirectPosition.coordinate>
            <DirectPosition.dimension>2</DirectPosition.dimension>
        </jps:DirectPosition>
    </jps:GM_Point.position>
</jps:GM_Point>
燃料給油所の所在地・店舗分類コード情報の部分
<ksj:FG01 id="FG01_00597">
    <ksj:POS idref="n00597"/>
    <ksj:FSC codeSpace="FuelStoreCd.xml">1</ksj:FSC>
    <ksj:ADS>愛知県稲沢市日下部北町3丁目XX-X</ksj:ADS>
</ksj:FG01>

位置情報と、所在地および店舗分類コードは、要素が分かれていますのでidとidref属性の値を使って対応する情報を結びつけます。このid属性の値は、都道府県ごとに同じ値が使用されているため、Data SourceのIDとしては使えません。本稿では都道府県ごとに異なる数値とこのid属性を合わせた値を使います。IDは一意の文字列であればなんでも構いません。

XMLファイルからData Source用のテキストファイルへの変換はどのような方法でもよいですが、サンプルとしてC#を利用した変換のコードを示しておきます。Visual Studioでコンソールアプリケーション プロジェクトを作成し、下記のコードを記述してください。

// 必要な using の宣言
//using System;
//using System.Collections.Generic;
//using System.IO;
//using System.Text.RegularExpressions;
//using System.Xml.Linq;

// 燃料給油所 情報のクラス
private class FuelStore
{
    public string Id { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
    public string Address { get; set; }
    public int Code { get; set; }
}

static private Dictionary<string, FuelStore> FuelStores = new Dictionary<string, FuelStore>();

// ひとつの XML ファイルから燃料給油所の情報を読み取る
static void LoadData(string prefix, string file)
{
    var doc = XDocument.Load(file);

    // 位置情報の読み取り
    XNamespace jps = "http://www.gsi.go.jp/GIS/jpgis/standardSchemas";
    foreach (var el in doc.Descendants(jps + "GM_Point"))
    {
        var store = new FuelStore();
        var coordinate = el.Element(jps + "GM_Point.position").Element(jps + "DirectPosition").Element("DirectPosition.coordinate").Value;
        var latlng = coordinate.Split(' ');

        store.Id = prefix + el.Attribute("id").Value;
        store.Latitude = Convert.ToDouble(latlng[0]);
        store.Longitude = Convert.ToDouble(latlng[1]);

        FuelStores.Add(store.Id, store);
    }

    // 所在地、店舗分類コードの読み取り
    XNamespace ksj = "http://nlftp.mlit.go.jp/ksj/schemas/ksj-app";
    foreach (var el in doc.Descendants(ksj + "FG01"))
    {
        var id = prefix + el.Element(ksj + "POS").Attribute("idref").Value;
        var code = Convert.ToInt32(el.Element(ksj + "FSC").Value);
        var address = el.Element(ksj + "ADS").Value;

        if (FuelStores.ContainsKey(id))
        {
            FuelStores[id].Code = code;
            FuelStores[id].Address = address;
        }
    }
}

static void Main(string[] args)
{
    // ダウンロードした XML ファイルがあるフォルダーのパスを指定
    var path = @"C:\Users\Owner\Documents\data";

    // P07-10_ で始まる .xml ファイルから情報を読み取る
    foreach (var file in System.IO.Directory.GetFiles(path, "P07-10_*.xml", SearchOption.AllDirectories))
    {
        var match = Regex.Match(file, "P07-10_(?<num>\\d+)\\.xml");
        LoadData(match.Groups["num"] + "-", file);
    }

    // Data Srouce 用テキストファイルを作成
    using (var fs = new FileStream("FuelStores.txt", FileMode.Create, FileAccess.Write))
    {
        using (var sw = new StreamWriter(fs, System.Text.Encoding.UTF8))
        {
            sw.WriteLine("Bing Spatial Data Services, 1.0, FuelStores");
            sw.WriteLine("ID(Edm.String,primaryKey)|Latitude(Edm.Double)|Longitude(Edm.Double)|Address(Edm.String)|Code(Edm.Int64)");

            foreach (var store in FuelStores.Values)
            {
                sw.WriteLine(string.Format("{0}|{1}|{2}|{3}|{4}", store.Id, store.Latitude, store.Longitude, store.Address, store.Code));
            }
        }
    }
}

コード中のフォルダーのパスを変更して実行すると、FuelStores.txtというファイルが作成されます。

最終的に次のような形式のテキストファイルが用意できれば準備完了です。

Bing Spatial Data Services, 1.0, FuelStores
ID(Edm.String,primaryKey)|Latitude(Edm.Double)|Longitude(Edm.Double)|Address(Edm.String)|Code(Edm.Int64)
01-n00001|43.78809074|142.39757271|北海道旭川市永山2条X丁目|1
01-n00002|43.76126172|142.37049301|北海道旭川市宮下通15丁目YYYY-Y|1
01-n00003|43.76244953|142.41265587|北海道旭川市豊岡6条7丁目Z-Z|1

ちなみに、できたファイルは約4MB、データの総数は49,262件でした。Bing Spatial Data Servicesで利用できるData Sourceは300MB程度までですので、まだまだ大きなデータを扱えます。

データのアップロード

作成したテキストファイルをアップロードして、Data Source作成のジョブを登録します。方法については、前回の内容を参照してください。

Bing Maps AJAX Control

今回は、Webページ用の地図コントロールのBing Maps AJAX Control図4と組み合わせてアプリを作ります。Bing Maps AJAX Controlは、JavaScriptライブラリーとして提供されていて、REST ServicesのBing Spatial Data Servicesとも簡単に連携が可能です。

図4 Bing Maps AJAX Control
図4 Bing Maps AJAX Control

Bing Maps AJAX Controlについては第1417回でも紹介していますので、詳しくはそちらを参照してください。連載時からいくつかアップデートがあり、地図上にポップアップ(ふきだし)の表示も可能になっています。その他、細かな機能追加やサポートするモバイルブラウザーが増えています。

図5 ポップアップの表示
図5 ポップアップの表示

地図の表示

最初に地図の表示部分を作ります。HTMLファイルに次のように記述します。Bing Maps AJAX ControlとjQueryのライブラリーを参照しています。Bing Maps AJAX Controlにも、Bing Maps Keyが必要です。今回はQuery APIに使用するクエリーキーと共用するものとしてコードを書いています。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8" />
        <title>Fuel Stores</title>
        <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.1.min.js" type="text/javascript"></script>
        <script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0&amp;mkt=ja-jp"></script>
        <script type="text/javascript">
            <!--
            $(function() {
                var map = null;
                var key = "BingMapsKey";

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

上記コードでは、Webページのロード後にMapオブジェクトを生成しています。このとき地図を表示するdiv要素を指定しています。以上で、地図の表示は完了です。

データの検索

次は、Query APIを利用して、地図の表示範囲にあるデータをData Sourceから取得します。地図をユーザーが操作して、表示の移動が終了した時点で取得するようにします。次のようにEventsオブジェクトを使用してMapオブジェクトのイベント処理を登録します。Mapオブジェクトの生成する次の行に追記します。

map = new Microsoft.Maps.Map(document.getElementById("map"), {credentials: key});
Microsoft.Maps.Events.addThrottledHandler(map, 'viewchangeend', loadData, 500);

Mapオブジェクトのviewchangeendイベントが発生すると、loadData関数を実行するように指定しています。地図の表示が変化するといった頻繁に起こるイベントに対してデータのリクエスト処理を記述すると、短時間に何度もサーバーへリクエストすることになってしまいます。EventsオブジェクトのaddThrottledHandlerメソッドを使用すると、第3引数で指定した時間(ミリ秒単位)を空けてイベントに関連付けたメソッドが呼ばれるようになります。単純にイベントを関連付けるにはaddHandlerメソッドを使用します。

続いてloadData関数を作成しましょう。ここでは、Bing Spatial Data Servicesへリクエストを行います。

検索する条件は、地図が表示されている範囲です。東西南北4点の経緯度で指定した領域内のデータを検索します。リクエスト方法については前回の内容を参照してください。4点の経緯度を指定する方法は、spatialFilterパラメーターを使用して次のように値を指定していました。

  • spatialFilter=bbox(35.90,139.66,36.05,139.84)

Mapオブジェクトの値を用いて、値を作成すると次のように記述できます。

var b = map.getBounds();
var s = b.getSouth();
var w = b.getWest();
var n = b.getNorth();
var e = b.getEast();
var bbox = "bbox(" + s + "," + w + "," + n + "," + e + ")";

HTTP GETメソッドでリクエストを行うコードは次のようになります。

function loadData() {
    // spatialFilter パラメーター値の作成
    var b = map.getBounds(); // LocationRect オブジェクトの取得
    var s = b.getSouth();
    var w = b.getWest();
    var n = b.getNorth();
    var e = b.getEast();
    var bbox = "bbox(" + s + "," + w + "," + n + "," + e + ")";
    
    // リクエストの送信
    $.ajax({
        type: "GET",
        url: "http://spatial.virtualearth.net/REST/v1/data/accessID/dataSourceName/FuelStores",
        dataType: "jsonp",
        data: { // リクエストパラメーター
            spatialFilter: bbox,
            key: key,
            $top: 250,
            $format: "json"
        },
        jsonp: "jsonp",
        success: function (data, dataType) {
            addPins(data);
        }
    });
}

リクエストURLのaccessIDは、Data Source作成時に得られるAccess IDを指定します。dataSourceNameには、Data Source作成時に指定したData Source名です。前回のサンプル通りに行うとGihyoSampleとなります。FuelStoresは、アップロードしたテキストファイル内に記載したエンティティの種類名です。

dataオブジェクトで、リクエストURLの各パラメーターを指定します。$topパラメーターでデータの最初から250件を取得するよう指定しています。Query APIで一度に取得できる結果は最大250件です。250件以上のデータを取得するには$top$skipパラメーターを使用して、複数回にわけてリクエストする必要があります。今回はその処理を記述していません。$formatでは、JSON形式のデータを指定しています。

データの取得に成功した場合、addPins関数を呼ぶように記述しています。次はaddPins関数を実装して、検索結果の表示です。

プッシュピンの表示

Query APIで取得した情報を使って、地図上にプッシュピンを配置しましょう。作成するアプリでは次の動作を行うよう実装します。

  • 燃料給油所の位置にプッシュピンを表示
  • 地図の表示範囲外に出たプッシュピンは地図上から削除
  • プッシュピンをクリックすると所在地をポップアップ表示
  • 地図のズームレベルを変更するとポップアップを非表示

プッシュピンとポップアップを分けて管理するため、それぞれのコレクションEntityCollectionを用意します。それぞれのコレクションにプッシュピンPushpinとポップアップInfoboxオブジェクトを追加し、地図にはこれらのコレクションを追加することで表示します。Mapオブジェクト生成部分のコードは次のようになります。

map = new Microsoft.Maps.Map(document.getElementById("map"), {credentials: key});
Microsoft.Maps.Events.addThrottledHandler(map, 'viewchangeend', loadData, 500);
Microsoft.Maps.Events.addThrottledHandler(map, "viewchange", hideInfobox, 500);

var pins = new Microsoft.Maps.EntityCollection();
var infoboxes = new Microsoft.Maps.EntityCollection();
map.entities.push(pins);
map.entities.push(infoboxes);

上記コードでは、後でポップアップの非表示で必要なイベントの登録も行っています。Mapオブジェクトのviewchangeイベントが発生するとhideInfobox関数を呼びます。

プッシュピンの削除と追加

addPins関数を作成します。ここでは、リクエストの結果を受け取ります。レスポンスの内容は次のようになっています。JSONPを使用したため、関数を呼び出す形になっています。実際に使用するのは、中身のJSONデータです。

jQuery16105611959514236509_1308656047043(
{
    "d": {
        "__copyright": "© 2011 Microsoft and its suppliers. (省略)", 
        "results": [
            {
                "Address": "兵庫県神戸市北区道場町日下部X", 
                "Code": 3, 
                "ID": "28-n01424", 
                "Latitude": 34.85762838, 
                "Longitude": 135.22473655, 
                "__metadata": {
                    "uri": "https://spatial.virtualearth.net/REST/v1/data/accessId/dataSourceName/FuelStores('28-n01424')"
                }
            }, 
            {
                (省略)
            }
        ]
    }
})

実際のデータは、日本語がエンコードされています。

データを見ると、dオブジェクトのresults配列に燃料給油所の情報が格納されていることがわかります。単純にPushpinを追加するコードは次のようになります。経緯度からLocationオブジェクトを生成し、Pushpinオブジェクトを生成します。

for (var i = 0; i < data.d.results.length; ++i) {
    var store = data.d.results[i];
    var loc = new Microsoft.Maps.Location(store.Latitude, store.Longitude);
    var pin = new Microsoft.Maps.Pushpin(loc);
    pins.push(pin); // EntityCollection に追加
}

実際には、地図の表示範囲外に出たプッシュピンをまず削除するようにします。あわせて、範囲内にあるプッシュピン情報も記録しておき、同じ情報のプッシュピンを追加しないようにします。

削除処理までを記述した、addPins関数の内容は次のようになります。

function addPins(data) {
    if (!data || !data.d || !data.d.results) {
        // 結果がない場合は処理を抜ける
        return;
    }

    // 画面外に移動した Pushpin の削除と、画面内にある Pushpin をチェック
    var addedPins = {};
    var bbox = map.getBounds(); // LocationRect オブジェクトの取得
    for (var i = pins.getLength() - 1; i >= 0; --i) {                    
        var pin = pins.get(i);
        if (!bbox.contains(pin.getLocation())) {
            // 表示範囲外の Pushpin はイベントの関連付けを削除してから EntityCollection からも削除
            Microsoft.Maps.Events.removeHandler(pin.clickHandler);
            pins.removeAt(i);
        } else {
            addedPins[pin.id] = true;
        }
    }

    // (ここに Pushpin を追加する処理を追記)
}

続いてPushpinの追加処理です。ここでは、同じ情報が重複しないようにPushpinオブジェクトを生成して追加します。また、ポップアップの表示ができるよう、Pushpinのclickイベントに関数を関連付けています。コードは次のようになります。

// 取得したデータ分の Pushpin を追加
for (var i = 0; i < data.d.results.length; ++i) {
    var store = data.d.results[i];

    if (addedPins[store.ID]) {
        // 既に追加している場合は次のデータへ
        continue;
    }

    var loc = new Microsoft.Maps.Location(store.Latitude, store.Longitude);
    var pin = new Microsoft.Maps.Pushpin(loc, {text: (store.Code == 2) ? "LP" : (store.Code == 3) ? "etc" : ""});
    
    // pin オブジェクトに独自のプロパティを設定し燃料料給油所の情報を保持
    pin.id = store.ID;
    pin.address = store.Address;
    pin.code = store.Code;
    
    // Pushpin のクリックイベントの関連付け
    pin.clickHandler = Microsoft.Maps.Events.addHandler(pin, "click", showInfobox);

    pins.push(pin); // EntityCollection に追加
}

おまけで、プッシュピンのテキストに、LPガススタンドの場合は「LP⁠⁠、燃料販売店の場合は「etc」と表示するようにしています。

ポップアップの表示

最後にポップアップ処理を記述します。イベントと関連付けて、まだ作成していないshowInfobox関数とhideInfobox関数を記述します。

ポップアップは、Infoboxオブジェクトを使います。今回のアプリでは「ガソリンスタンド」など店舗の種類と、所在地を表示するようにします。showInfobox関数は、次のように記述します。

function showInfobox (e) {
    infoboxes.clear(); // EntityCollection 内の Infobox を削除
    
    // クリックされた Pushpin の情報から Infobox を生成
    var pin = e.target;
    var infobox = new Microsoft.Maps.Infobox(pin.getLocation(), {
        title: (pin.code == 1) ? "ガソリンスタンド" : (pin.code == 2) ? "LPガススタンド" : "SS以外の燃料販売店",
        description: pin.address,
        offset: new Microsoft.Maps.Point(0, 20), 
        height: 100,
        visible: true});

    // Infobox を表示 (Infobox 用の EntityCollection に追加)
    infoboxes.push(infobox);
}

hideInfobox関数は、次のように記述します。ズームレベルに変化があった場合にポップアップを削除するようにします。表示が変更される前のズームレベルを記憶するため、あわせて変数も宣言します。


var zoom = 0;
function hideInfobox () {
    var targetZoom = map.getTargetZoom();
    if (zoom != targetZoom) {
        infoboxes.clear();
        zoom = targetZoom;
    }
}

ポップアップ処理は以上です。

アプリの実行

以上で、アプリの完成です。Webページを開いて、実行してみましょう。うまく動いたでしょうか。正しく動作していない場合は、もう一度、コードを確認してみてください。Internet Explorer 9の場合、F12 開発者ツール図6がデバッグに使えます。F12キーまたは、ギアのアイコンのメニューからF12 開発者ツールを起動します。

図6 F12 開発者ツール
図6 F12 開発者ツール

F12 開発者ツールを使えば、サーバーとの通信内容をキャプチャでき、レスポンスの内容がエラーかどうか確認もできます。ネットワークタブから「キャプチャの開始」ボタンをクリックし、地図を少し操作した後に、⁠キャプチャの停止」ボタンをクリックすると、通信内容がわかります図7、図8

図7 ネットワーク 概要ビュー
図7 ネットワーク 概要ビュー
図8 ネットワーク 詳細ビューの応答本文
図8 ネットワーク 詳細ビューの応答本文

図では、応答本文に正しく結果が返っているのがわかります。

実行するとわかるように、日本全体を表示している場合は250件のデータしか取得しないため、Data Sourceの先頭の北海道の情報のみ表示されてしまいます。一定以上のズームレベル以上の時のみプッシュピンを表示するなど工夫が必要ですね。ズームレベルで制限する場合は、loadData関数のはじめに次のように追記すれば可能です。

if (map.getZoom() < 10) {
    pins.clear();
    return;
}

地理情報以外の検索条件

これまで地理情報(経緯度)を用いた検索を行ってきましたが、別の条件で絞り込みや検索する方法についてもふれておきます。

まず、今回のアプリでガソリンスタンドだけ検索したいとします。つまりCodeプロパティが1のデータです。その場合は、$filterパラメーターをリクエストURLのパラメーターに加えます。

  • $filter=Code eq 1

Codeが1または2の場合は

  • $filter=Code eq 1 Or Code eq 2

となります。文字列の場合は、

  • $filter=Address eq '岩手県大船渡市末崎町字峰岸XXX-X'

のようにシングルクォーテーションを使って記述します。これらの仕様はODataのFilter System Query Optionに基づいています。ただし、すべてをサポートはしていません。使用できるのは、Logical OperatorsおよびGrouping Operatorsに区分されているものです。

演算子説明
Logical Operators
Eqイコール、等号(Equal)
Neノットイコール、等号否定(Not equal)
Gt大なり(>)⁠Greater than)
Ge大なりイコール(≧)⁠Greater than or equal)
Lt小なり(<)⁠Less than)
Le小なりイコール(≦)⁠Less than or equal)
And論理積(かつ)
Or論理和(または)
Not否定
Grouping Operators
()括弧による優先順位の指定
例:(A eq 'a' or B eq 'b'⁠⁠ and C eq 'c'

ガソリンスタンド アプリに、$filterパラメーターを追加した場合は、loadData関数のdataオブジェクトの指定が次のようになります。

data: {
    spatialFilter: bbox,
    key: key,
    $top: 250,
    $filter: "Code eq 1",
    $format: "json"
},

プロパティによる検索

プロパティの値のみを検索の条件にもできます。その場合のリクエストURLは次のようになります。

  • http://spatial.virtualearth.net/REST/v1/data/accessId/dataSourceName/entityTypeName?
      $filter=filterString&
      queryoption1&
      queryoption2&
       :
      queryoptionN&
      jsonp=jsonCallBackFunction&
      jsonso=jsonState&
      key=queryKey

地理情報によるデータ検索のときと比べて、spatialFilterパラメーターの代わりに$filterパラメーターを使用しているだけです。簡単ですね。その他のパラメーターについては前回の内容を参照してください。

IDによる検索

IDの値を条件とする場合は、URLの書式が変わります。ひとつのIDを指定する場合は次のようになります。

  • http://spatial.virtualearth.net/REST/v1/data/accessId/dataSourceName/entityTypeName(entityId)?
      jsonp=jsonCallBackFunction&
      jsonso=jsonState&
      key=queryKey

entityIdが、Data Sourceで定義したIDの値です。今回のアプリの場合、FuelStores('03-n0005')のようにIDを指定します。

IDの検索の場合、結果はひとつ、または無しとなりますので、その他の条件は指定できません。

複数のIDを一度に指定する場合は次のようになります。

  • http://spatial.virtualearth.net/REST/v1/data/accessId/dataSourceName/entityTypeName?
      $filter=entityId in (entityId1,entityId2,entityIdN)&
      queryoption1&
      queryoption2&
      queryoptionN&
      jsonp=jsonCallBackFunction&
      jsonso=jsonState&
      key=queryKey

複数の指定の場合は、$filterパラメーターを使用して、

  • $filter=FuelStores in ('03-n0005',' 23-n00597')

というように指定し、その他の条件の指定もできます。

ヒートマップの表示

おまけとして、ヒートマップを表示してみましょう。Bing Maps AJAX Controlには、ヒートマップ機能はありませんが、HTML5のCanvas機能を使ったAJAX Control用のライブラリーを公開している方がいますので、そのライブラリーを使用します。

Alastair Aitchisonからライブラリーのzipファイルをダウンロードします。そして、中に含まれているheatmap.jsを、アプリから参照するようにします。

<script type="text/javascript" src="heatmap.js"></script>

使い方は非常に簡単です。ガソリンスタンド アプリでは、最初にHeatMapLayerオブジェクトを生成し、レスポンスを受信するたびに、位置情報を設定するよう記述します。

まず、Mapオブジェクトを生成した後に次のコードを追記します。

var heatMapLayer = new HeatMapLayer(map, []);

そして、loadData関数内で、addPins関数を呼び出しているところを代わりに、showHeatMap関数を呼ぶように変更します。

success: function (data, dataType) {
    //addPins(data);
    showHeatMap(data);
}

showHeatMap関数の内容は次のように記述します。取得したデータからLocationオブジェクトの配列を作成し、HeatMapLayerオブジェクトのSetPoiontsメソッドに渡しています。

function showHeatMap(data) {
    if (!data || !data.d || !data.d.results) {
        return;
    }
  
    var locs = [];
    for (var i = 0; i < data.d.results.length; ++i) {                       
        var store = data.d.results[i];
        var loc = new Microsoft.Maps.Location(store.Latitude, store.Longitude);
        locs.push(loc);
    }
    heatMapLayer.SetPoints(locs);
}

以上で、ヒートマップが表示されるようになりました。位置情報が多いので、少し表示動作がもたつくかもしれません。

ライブラリー自体はもう少し機能があります。詳しくはサンプルやBlogを参照してください。また、執筆時点ではライブラリーのライセンスに関して、自由に使用してよい旨の記載があります。Webアプリ作成にぜひ活用してみてください。


今回は以上です。Bing Maps Data ServicesとBing Maps AJAX Controlを組み合わせた簡単なアプリを作ってみました。いかがでしたでしょうか。次回もBing Maps Data Servicesについてお届けする予定です。

おすすめ記事

記事・ニュース一覧