Google MapsとBing Mapsを使い比べる #2

前回に引き続き、Google MapsとBing Mapsを比較しながら、同じ機能を実装していきます。今回は、イベントハンドラ、吹き出し、図形を試してみます。

イベントハンドラを付ける

Google Maps

//マーカークリック
var markerClick = google.maps.event.addListener(marker, 'click', function(e) {
	console.log(e.latLng);
});
//マップクリック
var mapClick = google.maps.event.addListener(map, 'click', function(e) {
	console.log(e.latLng);
});

//除去
google.maps.event.removeListener(markerClick);
google.maps.event.removeListener(mapClick);

Bing Maps

//マーカークリック
var pushpinClick = Microsoft.Maps.Events.addHandler(pushpin, 'click', function(e) {
	console.log(e.target.getLocation());
});
//マップクリック
var mapClick = Microsoft.Maps.Events.addHandler(map, 'click', function(e) {
	var point = new Microsoft.Maps.Point(e.getX(), e.getY());
	var loc = e.target.tryPixelToLocation(point);
	console.log(loc);
});

//除去
Microsoft.Maps.Events.removeHandler(pushpinClick);
Microsoft.Maps.Events.removeHandler(mapClick);

どちらもイベントハンドラの付け方外し方はほぼ同じですが、Google Mapsの方は、この例のようにスタティックメソッドを使わず、対象オブジェクトのaddListenerメソッドを呼び出す方法も用意されています。

また、クリックイベントの場合、イベントハンドラ内で緯度経度を取得したい場合が多くあると思いますが、この方法はかなり異なります。
Google Mapsでは、イベントハンドラの引数のイベントオブジェクト内に、クリックが発生した緯度経度が入っているため、このまま使用できます。Map上でのクリックの場合はクリックした座標、Markerの上でクリックした場合は、マウス位置には関係なくMarkerが示す座標が入ります。
Bing Mapsでは、イベントオブジェクトには緯度経度は入らず、スクリーン上でのピクセル座標が入ります。Pushpinをクリックした場合には、イベントオブジェクトのtargetにPushpinのインスタンスが入るので、target.getLocation()で座標を取得できますが、Map上でのクリックの場合は、tryPixelToLocationでピクセル座標を緯度経度に変換する必要があります。

吹き出しを表示する

Google Maps

var infowindow = new google.maps.InfoWindow();
//マーカークリックで吹き出しを表示
var markerClick = google.maps.event.addListener(marker, 'click', function(e) {
	infowindow.setContent('<p>lat: ' + e.latLng.lat() + '<br>lng: ' + e.latLng.lng() + '</p>');
	infowindow.open(map, marker);
});

//閉じる
function closeInfoWindow() {
	infowindow.close();
}

Bing Maps

var infobox = new Microsoft.Maps.Infobox(map.getCenter(), {
	width: 160,
	height: 80
});
//マーカークリックで吹き出しを表示
var pushpinClick = Microsoft.Maps.Events.addHandler(pushpin, 'click', function(e) {
	infobox.setOptions({
		location: e.target.getLocation(),
		description: '<p>lat: ' + e.target.getLocation().latitude + '<br>lng: ' + e.target.getLocation().longitude + '</p>',
	});
	map.entities.push(infobox);
});

//閉じる
function closeInfobox() {
	map.entities.remove(infobox);
}

//

Google Mapsの吹き出しはInfoWindowです。内側に表示できるのは、文字列またはHTMLです。吹き出しのスタイルを変更するオプションはありません。サイズは内容に応じて自動調整されます。また、表示時に画面内に収まるよう、マップを自動的にパンする機能が標準で有効になっています。単独で座標を指定して表示する他に、Marker等の既存のオブジェクトの位置に表示する機能を持ちます。
Bing Mapの吹き出しは、Infoboxです。titleとdescriptionを指定して、それらしいスタイルで表示する機能を持つ他、吹出しの枠ごと指定したHTMLで上書きすることができます。サイズは例によって自分で設定する必要があります。座標は単独で保持していて、他のオブジェクトに関連付けるような機能はありません。また、×ボタンで閉じた場合、Mapのentitiesには入ったまま、オプションのvisibleがfalseになった状態であることにも注意が必要です。この状態で再度entitiesにpushしても、正しく表示されません。

手軽に使える代わりにカスタマイズする余地がほとんど無いのがGoogle Mapsで、Bing Mapsがその逆という感じでしょうか。

マップ上に図形を描く

Google Maps

//線
var path = [
	new google.maps.LatLng(35.6982813586945, 139.774643182754),
	new google.maps.LatLng(35.6981942296587, 139.775281548500),
	new google.maps.LatLng(35.6974296682867, 139.775268137455),
	new google.maps.LatLng(35.6974362030303, 139.774793386459)
];
var line = new google.maps.Polyline({
	path: path,
	strokeColor: "#000099",
	strokeWeight: 2
});
line.setMap(map);

//面
var paths = [
	new google.maps.LatLng(35.69740352930677, 139.77465257048607),
	new google.maps.LatLng(35.69711926734692, 139.77463781833650),
	new google.maps.LatLng(35.69711708909043, 139.77482289075851),
	new google.maps.LatLng(35.69740461843111, 139.77483227849007)
];
var rect = new google.maps.Polygon({
	paths: paths,
	fillColor: '#000099',
	fillOpacity: '0.5',
	strokeWeight: 0
});
rect.setMap(map);

Bing Maps

//線
var locations = [
	new Microsoft.Maps.Location(35.6982813586945, 139.774643182754),
	new Microsoft.Maps.Location(35.6981942296587, 139.775281548500),
	new Microsoft.Maps.Location(35.6974296682867, 139.775268137455),
	new Microsoft.Maps.Location(35.6974362030303, 139.774793386459)
];
var line = new Microsoft.Maps.Polyline(locations,{
	strokeColor:new Microsoft.Maps.Color(0xff, 0, 0, 0x99),
	strokeThickness:2
});
map.entities.push(line);

//面
var locations = [
	new Microsoft.Maps.Location(35.69740352930677, 139.77465257048607),
	new Microsoft.Maps.Location(35.69711926734692, 139.77463781833650),
	new Microsoft.Maps.Location(35.69711708909043, 139.77482289075851),
	new Microsoft.Maps.Location(35.69740461843111, 139.77483227849007)
];
var rect = new Microsoft.Maps.Polygon(locations,{
	fillColor: new Microsoft.Maps.Color(0x7F, 0, 0, 0x99),
	strokeThickness: 0
});
map.entities.push(rect);

線と多角形の描画についてはほぼ同じです。Google Mapsには、この他に四角形と円を描くためのクラスも用意されています。Polygonで円を描くのは非常に手間がかかるので、円を描く機能の有無の差は大きいかもしれません。また、Bing Mapsでは、色指定を行う際にColorオブジェクトを作って渡す必要がありますが、コンストラクタの引数がA,R,G,Bの順になっているので注意が必要です。筆者は、他の言語の慣例からR,G,B,Aの順だと思い込んでしまい、指定した色が出なくてしばらく悩んでしまいました。

まとめ

ここまでの内容でマップを描画したサンプルを以下に載せておきます。クラスメソッドの場所と、最寄りのJR秋葉原駅の昭和通り口からの道筋を表示しています。

Google Maps

(function() {
	//地図
	var latlng = new google.maps.LatLng(35.69734, 139.77475);
	var myOptions = {
		zoom: 17,
		center: latlng,
		mapTypeId: google.maps.MapTypeId.ROADMAP
	};
	var map = new google.maps.Map(document.getElementById("googleMapsDiv"), myOptions);

	//ピン
	var markerOptions = {
		position: map.getCenter(),
		icon: 'logo.png',
		map: map
	};
	var marker = new google.maps.Marker(markerOptions);

	//吹き出し
	var infowindow = new google.maps.InfoWindow();
	var markerClick = google.maps.event.addListener(marker, 'click', function(e) {
		infowindow.setContent('<h3>クラスメソッド株式会社</h3><p>lat: ' + e.latLng.lat() + '<br>lng: ' + e.latLng.lng() + '</p>');
		infowindow.open(map, marker);
	});

	//駅からの道筋
	var path = [
		new google.maps.LatLng(35.6982813586945, 139.774643182754),
		new google.maps.LatLng(35.6981942296587, 139.775281548500),
		new google.maps.LatLng(35.6974296682867, 139.775268137455),
		new google.maps.LatLng(35.6974362030303, 139.774793386459)
	];
	var line = new google.maps.Polyline({
		path: path,
		strokeColor: "#000099",
		strokeWeight: 2
	});
	line.setMap(map);

	//建物
	var paths = [
		new google.maps.LatLng(35.69740352930677, 139.77465257048607),
		new google.maps.LatLng(35.69711926734692, 139.77463781833650),
		new google.maps.LatLng(35.69711708909043, 139.77482289075851),
		new google.maps.LatLng(35.69740461843111, 139.77483227849007)
	];
	var rect = new google.maps.Polygon({
		paths: paths,
		fillColor: '#000099',
		fillOpacity: '0.5',
		strokeWeight: 0
	});
	rect.setMap(map);
})();

Bing Maps

(function() {
	//地図
	var latlng = new Microsoft.Maps.Location(35.69734, 139.77475);
	var mapOptions = {
		zoom: 17,
		center: latlng,
		credentials: '*****************************************',
		mapTypeId: Microsoft.Maps.MapTypeId.road,
		width: 400,
		height: 400
	};
	var map = new Microsoft.Maps.Map(document.getElementById('bingMapsDiv'), mapOptions);

	//ピン
	var pushpinOptions = {
		icon: 'logo.png',
		width: 40,
		height: 40}; 
	var pushpin = new Microsoft.Maps.Pushpin(map.getCenter(), pushpinOptions);
	map.entities.push(pushpin);

	//吹き出し
	var infobox = new Microsoft.Maps.Infobox(map.getCenter(), {
		title: 'クラスメソッド株式会社',
		width: 200,
		height: 100
	});
	var pushpinClick = Microsoft.Maps.Events.addHandler(pushpin, 'click', function(e) {
		infobox.setOptions({
			visible: true,
			location: e.target.getLocation(),
			description: 'lat: ' + e.target.getLocation().latitude + '<br>lng: ' + e.target.getLocation().longitude
		});
		map.entities.push(infobox);
	});

	//駅からの道筋
	var locations = [
		new Microsoft.Maps.Location(35.6982813586945, 139.774643182754),
		new Microsoft.Maps.Location(35.6981942296587, 139.775281548500),
		new Microsoft.Maps.Location(35.6974296682867, 139.775268137455),
		new Microsoft.Maps.Location(35.6974362030303, 139.774793386459)
	];
	var line = new Microsoft.Maps.Polyline(locations,{
		strokeColor:new Microsoft.Maps.Color(0xff, 0, 0, 0x99),
		strokeThickness:2
	});
	map.entities.push(line);

	//建物
	var locations = [
		new Microsoft.Maps.Location(35.69740352930677, 139.77465257048607),
		new Microsoft.Maps.Location(35.69711926734692, 139.77463781833650),
		new Microsoft.Maps.Location(35.69711708909043, 139.77482289075851),
		new Microsoft.Maps.Location(35.69740461843111, 139.77483227849007)
	];
	var rect = new Microsoft.Maps.Polygon(locations,{
		fillColor: new Microsoft.Maps.Color(0x7F, 0, 0, 0x99),
		strokeThickness: 0
	});
	map.entities.push(rect);
})();

次回は、マップ上の各種コントロールの制御とカスタムコントロールの追加等について解説する予定です。