読者です 読者をやめる 読者になる 読者になる

Google Maps Javascript API v3でv2みたいな情報ウィンドウの制御

来るべき5月19日に向けてDamMapsを作り直してるんですけど、その絡みでちょっとしたTipsを。
Google Maps Javascript API v3の情報ウィンドウ(InfoWindow)は機能が強化されて一度に2つ以上の情報ウィンドウを開くとことが出来るようになりました。
でも、実際のところ通常の使い方では一度に一つ、別のを開いたときは開いていたのを閉じるというAPI v2の動作が使いやすかったり。なのでこの動きをv3でも再現したいと思った訳ですが、どうやるかあれこれ試してみて一番良さげだった方法を書いてみます。

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
	<title>Google Maps Javascript API v3でv2みたいな情報ウィンドウの制御のサンプル</title>
	<script type="text/javascript"
      src="http://maps.googleapis.com/maps/api/js?key=&sensor=false">
    </script>
    <script type="text/javascript">
      function initialize() {
		
	//Mapオブジェクトを作成して地図を表示
        var mapOptions = {
          center: new google.maps.LatLng(35, 135),
          zoom: 10,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        var map = new google.maps.Map(document.getElementById("map_canvas"),
            mapOptions);

	//情報ウィンドウオブジェクトを作成する
	var w = new google.maps.InfoWindow();
		
	//左のマーカーを作成して表示
	var m1 = new google.maps.Marker({
		position: new google.maps.LatLng(35,134.9 )
	});
	m1.setMap(map);
		
	//左のマーカーがクリックされたら情報ウィンドウを表示
	google.maps.event.addListener(m1, "click", function(){
		w.setContent("m1");
		w.open(map, m1);
	});
		
	//右のマーカーを作成して表示
	var m2 = new google.maps.Marker({
		position: new google.maps.LatLng(35,135.1)
	});
	m2.setMap(map);
		
	//右のマーカーがクリックされたら情報ウィンドウを表示
	google.maps.event.addListener(m2, "click", function(){
		w.setContent("m2");
		w.open(map, m2);
	});
		
	//地図がクリックされたら情報ウィンドウを閉じる
	google.maps.event.addListener(map, "click", function(){
		w.close();
	});
      }
    </script>
  </head>
  <body onload="initialize()">
	<h1>Google Maps Javascript API v3でv2みたいな情報ウィンドウの制御のサンプル</h1>
    <div id="map_canvas" style="width:600px; height:400px;"></div>
  </body>
</html>

デモページ

コードご覧頂くと分かると思いますが、ポイントは一つのInfoWindowオブジェクトを使い回すことですね。
検索すると同様な事を行う為のサンプルコードがいくつか見つかるのですが、それらはInfoWindowのオブジェクトを都度生成し、開くときにそのオブジェクトを変数に取っておいて、別のInfoWindowを開くときにそれをつかってInfoWindowを閉じるという手順で実現してます。
で、それで問題ないかなーと思ってたのですが、Markerオブジェクトが地図に表示されていない状態でそれにくっついてるInfoWindowを閉じようとしてもどうもうまく行かないんですね。具体的にはMarkerManagerを使った時にやろうとするとうまく行かなくなる。
で、どうやったらいいのかなーとあれこれ試しているうちに、常に一つしか情報ウィンドウ表示しないんだから、一つのオブジェクトを使い回せばいいんじゃんということに気付いて試したらなんかうまくいったのでとりあえずブログに書きました。
状態管理する変数とか閉じる処理とかいらなくなるので、こっちのほうがシンプルでよさげじゃないですかね。

追記(2013/04/19)

これもAPIのドキュメントに書いてありました。

https://developers.google.com/maps/documentation/javascript/overlays?hl=ja#InfoWindows
InfoWindow は、Marker オブジェクト(この場合、ウィンドウの位置はマーカーの位置に基づきます)、または地図上の LatLng の指定位置に固定されます。同時には 1 つのウィンドウのみ表示したい場合(Google マップの動作と同じ)、情報ウィンドウを 1 つだけ作成し、マップ イベント(クリックなど)により別の地点や、マーカーに再割り当てします。Google Maps API V2 とは異なり、地図上に複数の InfoWindow オブジェクトを表示できるようになりました。

ドキュメントもっとちゃんと読まねば…。