Windows Phone 7を使っていて、スマートフォントして有り得ないと思うものがあります。少なくともこのまま行けば、Windows Phone 7は酷評されて日本で日の目を見ません。それは何か?
Bing Mapです。
梅田の付近のこのレベル。まだ日本ではローンチされていないからと言っても、外国の方で日本に旅行で来る人もいるでしょう。このままではWindows Phone 7を使っている外国の方に悪いイメージを与えかねない。
……ってことで、Bing Map Control上でGoogle Mapの画像を使うTipsをご紹介したいと思います。Bing MapもGoogle Mapも再接近時の地図の大きさで言うと、1,073,741,824ピクセルx1,073,741,824ピクセルの超巨大な画像です(ちなみに10億x10億ですね)。
Bing Mapには、Deep Zoomと呼ばれる技術が使われています。Deep Zoomというのは、超高画質の画像を例えば256ピクセルx256ピクセルと言った小さなタイルに分割して、描画に必要な箇所のタイルだけを読み込み、スムーズなズームイン、ズームアウト、スクロール(パン)を実現させることができます。
このタイルを読み込む箇所が、Bing Mapコントロールでは、Microsoft.Phone.Controls.Maps.TileSourceクラスの以下のメソッドになります。
Uri GetUri(int x, int y, int zoomLevel)
タイルを読み込むGetUriメソッドをオーバーライドして、本来のBing Mapの画像ではなく、Google Mapの画像を渡すようにしてしまえば勝ちですね。
やり方としては、まず名前空間を追加します。
xmlns:mapCtrl="clr-namespace:Microsoft.Phone.Controls.Maps;assembly=Microsoft.Phone.Controls.Maps" xmlns:gMapEx="clr-namespace:GoogleMapsSample" xmlns:device="clr-namespace:System.Device.Location;assembly=System.Device">
次にBing Map Controlを貼り付けましょう。この辺りは詳しくはサンプルプロジェクトを添付しますので、そちらの方を見てくださってもOKです。CredentialsProviderプロパティは自分のものを使ってくださいね。
ちなみにアプリキーを取得したい方は、第20回 Bing Mapsで遊んでみよう!(1) :Windows Phoneアプリケーション開発入門|gihyo.jp … 技術評論社のBing Maps Keyの取得方法あたりを見てくださいね。
<mapCtrl:Map Height="610" HorizontalAlignment="Left" Name="map1" VerticalAlignment="Top" Width="456" CredentialsProvider="your app key" ZoomLevel="16"> <mapCtrl:Map.Center> <device:GeoCoordinate Altitude="NaN" Course="NaN" HorizontalAccuracy="NaN" Latitude="34.701189" Longitude="135.496016" Speed="NaN" VerticalAccuracy="NaN" /> </mapCtrl:Map.Center> <mapCtrl:Map.Children> <mapCtrl:MapTileLayer> <mapCtrl:MapTileLayer.TileSources> <gMapEx:GoogleTileSource TileSourceType="Satellite" /> </mapCtrl:MapTileLayer.TileSources> </mapCtrl:MapTileLayer> <mapCtrl:MapTileLayer> <mapCtrl:MapTileLayer.TileSources> <gMapEx:GoogleTileSource TileSourceType="Street" /> </mapCtrl:MapTileLayer.TileSources> </mapCtrl:MapTileLayer> </mapCtrl:Map.Children> </mapCtrl:Map>
XAMLで使ったGoogleTileSourceクラスとTileSourceType型を定義する必要があります。適当にGoogleTileSource.csといったソースを新規作成してコピペしてください。
XAMLで名前空間を指定していますので、名前空間はGoogleMapsSampleを使ってください。必要あれば適切に変更をお願いします。
namespace GoogleMapsSample { public enum GoogleTileSourceType { Street, Hybrid, Satellite, Physical, PhysicalHybrid, StreetOverlay, WaterOverlay } public class GoogleTileSource : Microsoft.Phone.Controls.Maps.TileSource { public GoogleTileSource() { UriFormat = @"http://mt{0}.google.com/vt/lyrs={1}&z={2}&x={3}&y={4}"; TileSourceType = GoogleTileSourceType.Street; } private int _servernr; private char _mapMode; private int Server { get { return _servernr = (_servernr + 1) % 4; } } private GoogleTileSourceType _tileSourceType; public GoogleTileSourceType TileSourceType { get { return _tileSourceType; } set { _tileSourceType = value; _mapMode = TypeToMapMode(value); } } public override Uri GetUri(int x, int y, int zoomLevel) { if (zoomLevel > 0) { var url = string.Format(UriFormat, Server, _mapMode, zoomLevel, x, y); //System.Diagnostics.Debug.WriteLine(url); return new Uri(url); } return null; } private static char TypeToMapMode(GoogleTileSourceType tileSourceType) { switch (tileSourceType) { case GoogleTileSourceType.Hybrid: return 'y'; case GoogleTileSourceType.Satellite: return 's'; case GoogleTileSourceType.Street: return 'm'; case GoogleTileSourceType.Physical: return 't'; case GoogleTileSourceType.PhysicalHybrid: return 'p'; case GoogleTileSourceType.StreetOverlay: return 'h'; case GoogleTileSourceType.WaterOverlay: return 'r'; } return ' '; } } }
さて、これを実行してGoogle MapとBing Mapを並べてみました。
Bing MapとGoogleが同じ256ピクセルx256ピクセルの画像を使っていたので、出来る技ですね。ちなみにYahoo!地図なんかも同じサイズのタイルを使っているので、ひょっとしたら同じことが出来るかもしれないです。
日本人には、Google MapよりもYahoo!地図の方がマッチしているかもしれないので、必要な方はGetUriメソッドを差し替えてそれっぽく書き換えてください。
ちなみにYahoo!地図のURLは、「http://ta.map.yahoo.co.jp/yta/map?v=4.3&r=1&x={0}&y={1}&z={2}」です。お試しあれ。