使ってみよう! Bing API/SDK

第4回Hello, Bing Map App!─⁠─Silverlightで作るBing Mapsアプリケーション(4)

はじめに

今回のBing Map App開発では、地図上に表示する各種エンティティについて紹介します。

第1回目の内容からおさらいすると、プラグインはひとつ以上のレイヤーを持っています。レイヤー上にはプッシュピン図1などエンティティと呼ばれる地図上に表示するアイテムを追加可能でした。

図1 プッシュピン 図1 プッシュピン

今回は、プッシュピン、ポリライン、ポリゴンを地図上に表示してみましょう。また最後にダイアログの表示についても触れています。

プッシュピン

最初に、プッシュピンを地図に表示してみましょう。基本的なプッシュピンの追加方法は、第1回でも紹介しています。これまでの内容も参考にプラグインのプロジェクトを作成してください。Visual StudioのC#のBing Map Appプロジェクトテンプレートを利用すると、プッシュピンがひとつ追加されるプラグインのコードが生成されています。

プッシュピンを地図上に追加するプラグインのコードは次のようになります。PushpinFactoryContractCreateStandardPushpinメソッドを使用して、ひとつの地点の情報を表すPointPrimitiveオブジェクトを作成します。これをEntityクラスのPrimitiveプロパティに指定し、レイヤー上に追加しています。

namespace HelloWorldBingMapApp
{
    using System;
    using System.Windows.Media;
    using Microsoft.Maps.Core;
    using Microsoft.Maps.Plugins;
    using Microsoft.Maps.Network;
    using Microsoft.Maps.MapControl;
 
    public class EmptyLayer : Layer {
        public EmptyLayer(PluginToken pluginToken) : base(pluginToken) { }
    }
    
    public class EntitySamplePlugin : Plugin
    {
        private EmptyLayer mainLayer;
 
        [ImportSingle("Microsoft/LayerManagerContract", ImportLoadPolicy.Synchronous)]
        public LayerManagerContract LayerManagerContract { get; set; }
 
        [ImportSingle("Microsoft/MapContract", ImportLoadPolicy.Synchronous)]
        public MapContract DefaultMap { get; set; }
 
        [ImportSingle("Microsoft/PushpinFactoryContract", ImportLoadPolicy.Synchronous)]
        public PushpinFactoryContract PushpinFactoryContract { get; set; }
 
        public override void Initialize()
        {
            base.Initialize();
            this.mainLayer = new EmptyLayer(this.Token);
            DefaultMap.MouseClick += new EventHandler<MapMouseEventArgs>(DefaultMap_MouseClick);
        }
 
        void DefaultMap_MouseClick(object sender, MapMouseEventArgs e)
        {
            // クリックした場所からその経緯度を取得
            var location = DefaultMap.ViewportPointToLocation(e.ViewportPoint);
 
            // プッシュピンの作成
            var pin = PushpinFactoryContract.CreateStandardPushpin(location);
 
            var entity = new Entity();
            entity.Primitive = pin; // Entity(pin) でも可
 
            // レイヤーにエンティティを追加
            this.mainLayer.Entities.Add(entity);
        }
 
        public override void Activate(System.Collections.Generic.IDictionary<string, string> activationParameters)
        {
            if (LayerManagerContract.ContainsLayer(this.mainLayer))
            {
                LayerManagerContract.BringToFront(this.mainLayer);
            }
            else
            {
                LayerManagerContract.AddLayer(this.mainLayer);
            }
         }
    }
}

上記コードでは、地図をクリックした地点にプッシュピンを追加しています。これを元にいろいろと変更を加えていきます。

さまざまなプッシュピン

プッシュピンは簡単に見た目の変更も可能です。

Colorプロパティで色の変更図2ができます。

pin.Color = Colors.Purple;
図2 色の変更
図2 色の変更

また、メソッドの引数にテキストを指定すると、その文字をプッシュピン上に表示できます図3⁠。日本語だと1文字がバランスよく表示されます。最大3文字まで表示可能です。また、HighlightedStateプロパティを使用するとアニメーションで目立たせることができます。

var pin = PushpinFactoryContract.CreateStandardPushpin(location, "あ");
pin.HighlightedState = HighlightedState.Highlighted;
図3 テキストの表示
図3 テキストの表示

アイコンの表示もできます図4⁠。Entityの内容からアイコン画像を設定したUIElementオブジェクトを返すメソッドを用意して、CreateStandardPushpinメソッドに指定します。

System.Windows.UIElement GetPinIcon(Entity entity)
{
    // ここでは entity を利用せず、決まった画像の Image オブジェクトを返す。
    var bmp = new System.Windows.Media.Imaging.BitmapImage(new Uri("http://example.jp/pinicon.png"));
    return new System.Windows.Controls.Image() {Source = bmp};
}
var pin = PushpinFactoryContract.CreateStandardPushpin(location, GetPinIcon);
図4 アイコンの表示
図4 アイコンの表示

さらに、メソッド名CreateStandardPushpinにあるように、Standardでないプッシュピンを作るメソッドも用意されています。

CreateMediaPushpinメソッドを使用すると、動画像をプッシュピンとして使用できます図5⁠。アイコンを指定したときと同じようにUIElementオブジェクト返すメソッド引数に指定します。

var pin = PushpinFactoryContract. CreateMediaPushpin(location, GetPinIcon);
図5 メディアプッシュピン
図5 メディアプッシュピン

CreateMiniPushpinメソッドを使用すると、小さいプッシュピンを作れます図6⁠。

var pin = PushpinFactoryContract. CreateMiniPushpin(location);
図6 ミニプッシュピン
図6 ミニプッシュピン

クラスタリング

多数のプッシュピンを表示した場合、ズームレベルによってはプッシュピンが重なって表示されてしまいます。クラスタリング機能を使うと、プッシュピンが密集して表示されるようなとき、それらをまとめてひとつプッシュピンとして表示し、クリック動作で各プッシュピンを選択できるようになります図7図8⁠。プラス記号が付いたものがクラスタリングされたプッシュピンです。

図7 プッシュピンのクラスタリング  閉じた状態
図7 プッシュピンのクラスタリン
図8 プッシュピンのクラスタリング  展開した状態
図8 プッシュピンのクラスタリン

このクラスタリングを行うには、EntityClusteringContractというContractを使用します。これまでと同様にプロパティを定義します。

[ImportSingle("Microsoft/EntityClusteringContract", ImportLoadPolicy.Synchronous)]
public EntityClusteringContract EntityClusteringContract { get; set; }

そして、作成したエンティティをRegisterメソッドに渡すだけです。

void DefaultMap_MouseClick(object sender, MapMouseEventArgs e)
{
    // クリックした場所からその経緯度を取得
    var location = DefaultMap.ViewportPointToLocation(e.ViewportPoint);

    // プッシュピンの作成
    var pin = PushpinFactoryContract.CreateStandardPushpin(location);
    var entity = new Entity(pin);

    // クラスタリング指定
    EntityClusteringContract.Register(entity);

    // レイヤーにエンティティを追加
    this.mainLayer.Entities.Add(entity);
}

こうすると、登録したプッシュピンは、必要なときに自動でクラスタリングされ表示されます。逆に、細かな制御はできません。

ポリライン

次にポリライン(polyline)を使ってみましょう図9⁠。ポリラインを使用すると地図上に線を引くことができます。ルート探索などで使用されるものですね。

図9 ポリライン
図9 ポリライン

このポリラインもプッシュピンと同様にエンティティのひとつです。プッシュピンではある1点を指すものでしたが、ポリラインでは複数の地点を指定して、線を描画します。

プッシュピンのようにContractを使用するのではなく、PolylinePrimitveオブジェクトを直接生成します。以下にコードを示します。

// 線を引く地点
var location = DefaultMap.ViewportPointToLocation(e.ViewportPoint);
var locations = new LocationCollection();
var lat = location.Latitude;
var lng = location.Longitude;
locations.Add(new Location(lat, lng));
locations.Add(new Location(lat - 0.1, lng + 0.1));
locations.Add(new Location(lat, lng + 0.2));
locations.Add(new Location(lat + 0.1, lng + 0.15));
locations.Add(new Location(lat + 0.1, lng + 0.05));
locations.Add(new Location(lat, lng));

// PolylinePrimitive オブジェクトの作成
var polyline = new PolylinePrimitive(locations, new SolidColorBrush(Colors.Red));

// レイヤーにポリラインの追加
this.mainLayer.Entities.Add(new Entity(polyline));

StrokeThicknessプロパティやStrokeDashArrayプロパティを使用すると、線の太さや点線の描画なども可能です図10⁠。各プロパティの型はMap App SDKライブラリーに含まれるものではなくSilverlightの標準で用意されているものですので、一般的方法で描画が可能です。

// 太さ
polyline.StrokeThickness = 5;

// 点線
var doubles = new DoubleCollection();
doubles.Add(0.5);
doubles.Add(1);
doubles.Add(0.5);
doubles.Add(1);
polyline.StrokeDashArray = doubles;
図10 太さの変更や点線の描画
図10 太さの変更や点線の描画

ポリゴン

次はポリゴン(polygon)です図11⁠。ポリゴンを使うと地図上の領域を示すことができます。ポリラインのように複数地点を指定して形成しますが、線ではなく閉じた面として表示されます。

図11 ポリゴン
図11 ポリゴン

ポリラインと同じように直接、PolygonPrimitiveオブジェクトを生成して使います。コードは次のようになります。

var location = DefaultMap.ViewportPointToLocation(e.ViewportPoint);
var locations = new LocationCollection();
var lat = location.Latitude;
var lng = location.Longitude;
locations.Add(new Location(lat, lng));
locations.Add(new Location(lat - 0.1, lng + 0.1));
locations.Add(new Location(lat, lng + 0.2));
locations.Add(new Location(lat + 0.1, lng + 0.15));
locations.Add(new Location(lat + 0.1, lng + 0.05));

// PolygonPrimitive オブジェクトの作成
var polygon = new PolygonPrimitive(
    locations, 
    new SolidColorBrush(Colors.Green), 
    new SolidColorBrush(Color.FromArgb(128, 255, 0, 0)));

// レイヤーにポリラインの追加
this.mainLayer.Entities.Add(new Entity(polygon));

Brushを変更すればグラデーションや半透明の描画も、通常のSilverlightアプリケーションと同様に可能です図12⁠。

var gss = new GradientStopCollection();
gss.Add(new GradientStop() { Color = Colors.Red, Offset = 0 });
gss.Add(new GradientStop() { Color = Colors.Orange, Offset = 0.2 });
gss.Add(new GradientStop() { Color = Colors.Yellow, Offset = 0.4 });
gss.Add(new GradientStop() { Color = Colors.Green, Offset = 0.6 });
gss.Add(new GradientStop() { Color = Color.FromArgb(255, 0, 0, 0x80), Offset = 0.8 });
gss.Add(new GradientStop() { Color = Colors.Purple, Offset = 1 });
var brush = new LinearGradientBrush(gss, 0);

// PolygonPrimitive オブジェクトの作成
var polygon = new PolygonPrimitive(
    locations, 
    new SolidColorBrush(Colors.Red), 
    brush);

// レイヤーにポリラインの追加
this.mainLayer.Entities.Add(new Entity(polygon));
図12 グラデーションの描画
図12 グラデーションの描画

ダイアログの表示

最後に、エンティティではないですが、ダイアログ図13の表示方法についても紹介しておきます。パネルのコントロールやエンティティをクリックしたときなどに、何かしらのダイアログを表示したい場合、ModalDialogContractが使えます。

図13 ダイアログ
図13 ダイアログ

使い方は、次のようにプロパティを定義して、Openメソッドを呼ぶだけです。

[ImportSingle("Microsoft/ModalDialogContract", ImportLoadPolicy.Synchronous)]
public ModalDialogContract ModalDialogContract { get; set; }

たとえば、プッシュピンのクリック時にダイアログを表示したい場合次のように記述します。

var pin = PushpinFactoryContract.CreateStandardPushpin(location);
var entity = new Entity(pin);

pin.MouseLeftButtonDown += (s, e1) =>
{
    ModalDialogContract.Open("タイトル",
        new System.Windows.Controls.TextBlock()
        {
            Text = "メッセージ",
            Margin = new System.Windows.Thickness(30)
        });
};

Openメソッドの引数は、ダイアログのタイトルとコンテンツ部分です。上記では単にTextBlockを指定していますが、ユーザーコントロールを用意して自由な内容を表可能です。

おわりに

今回はここまでです。いかがでしたでしょうか。地図系アプリの基本的な機能とも言える、プッシュピンや線や領域の描画について紹介しました。

今回の内容を、Bing Maps Silverlight Controlと比較したとき、表示できるものがMap Appのほうが制限されています。Silverlight ControlはSilverlight のコントロールを自由に配置でき、ズームに併せて大きさの変化する動画像の貼り付けなども可能です。一方、プッシュピンに関しては、両方対応していますが、Map Appのほうが選択時の見た目の変化に対応していたり、クラスタリングが可能だったりと機能が豊富です。

このように似たソリューションでも違いがあり、Map Appを作成するときもSilverlight Controlの機能も調べてみると、両者の違いが見え、より良いアプリ開発につながるかも知れませんね。

おすすめ記事

記事・ニュース一覧