<目次>始めに地図を読み込んだ時、複数のマーカーから任意の一つのインフォウィンドウ(infowindow)を最初から表示する。
- (その1)外部XMLファイルでなく内部ソースにマーカー用の配列を記述する。
- (その2)マーカーのインフォウィンドウ(吹き出し)を地図の中心座標に表示させるpanTo()メソッドを使ったサンプル
- (その3)イベントリスナー’dragstart’で、地図をドラッグしたらマーカーのインフォウィンドウ(吹き出し)を閉じて削除する。
- (その4)マーカー(アイコン)の配列についての検証(2次元配列を理解してみる)
- (その5)XMLファイル(配列)の複数マーカーから特定markerのインフォウィンドウ(infowindow)を最初から一つだけ表示するサンプルデモ完成
◆ インフォウィンドウ(infowindow)を最初から一つだけ表示する方法の検討
さて、前回配列から特定の要素だけ取り出すことができましたので、最初に作ったサンプル地図に合わせていきます。
結局、最初に思いついたのが、for (var i = 0; i < markers.length; i++) で、配列から全てのマーカーを表示させておき、別のfor文でインフォウィンドウを最初から地図に表示させたい特定のマーカーの要素を、for (var i = 6; i <= 6; i++) (この場合6番目の要素)で取り出す案です。・・・というかコレぐらいしか思いつきませんでした。
試していきます。
さて、ここで作ったサンプルマップに、2つめの特定の要素を読み出すfor文を追加します。
for (var i = 0; i < markers.length; i++)で配列からマーカーデータを読み込んだあとに、再度、for (var i = 6; i <=6; i++)で6番目の要素をとりにいきます。つまり、6番目の要素(水族館1)だけは、2度マーカーを読み込むことになります。多少影が濃くなりますが機能上は変わりませんので、このまま進めます。(どうしても気になる場合は、回避策が考えられます。本件での実現は未検討)
また、コードの最後に、先に説明したマップクラスのpanTo()メソッドを追加しておきます。
for (var i = 6; i <=6; i++) { var marker = markers[i]; var name = marker[0]; var latlng = new google.maps.LatLng(marker[1], marker[2]); var category = marker[3]; var html = '<div style="height: 100px; width: 200px"><b>'+name+'</b>' ; createMarker(latlng,html,map,category,name) map.panTo( latlng); }
2.地図画面が表示されたらinfowindowをオープンさせるイベントの追加
先にも説明済みですが、マーカーデータを配列から収得後、地図が表示されるきに一緒にインフォウィンドウも開くようにします。これには、地図が表示されたときに発生する都合のいいマップイベントprojection_changedがありますので、これを使います。 (‘projection_changed’とは?)
地図が表示されるとinfoWindow.setContent(html); 、infoWindow.open(map,marker); にイベントをハンドルすることが出来ます。
下記コードを追加。
google.maps.event.addListener(map, 'projection_changed', function() //◆地図が表示された時 { infoWindow.setContent(html); //◆インフォウィンドウ内に表示するコンテンツをセット infoWindow.open(map,marker); //◆インフォウィンドウオープン });
以上で完成です。まあ配列を外部(XMLファイル)に置かない版のサンプルでは動きました。
3.外部XMLファイルからマーカーを読み込む地図でも試してみる。
つづいて、この外部XMLファイルからマーカーデータを読み込んでいるサンプル地図(サイドバー付)でも、上記同様に地図が表示された時点で、一緒にinfowindowを開けるようにしてみる。
downloadUrl(“http://waox.main.jp/news/maps/googlemapsapi/example/kouen-demo.php“, function(data)には、拡張子.phpが指定されていますが、中身はXMLファイルで、126マーカー(アイコン)のデータです。
XMLファイル(php)のデータは、こんな感じのものです。ちなみに変数zoomは、今回無関係です。
<markers> <marker zoom="11" lat="42.932918" lng="143.312016" category="kouen" name="北海道十勝エコロジーパーク"/> <marker zoom="8" lat="39.750622" lng="141.016693" category="kouen" name="小岩井農場 まきば園"/> <marker zoom="7" lat="35.708364" lng="139.396806" category="kouen" name="昭和記念公園" /> <marker zoom="10" lat="38.16457" lng="140.39491" category="onsen" name="湯の花茶屋 新左衛門の湯"/> </markers>
このXMLファイルの上から5番目(配列の5番目の要素)に「(あ)奥多摩温泉もえぎの湯」があります。後ほど下記のサンプルのサイドバーを見ていただければ、上から6番目(配列要素は0からはじまるので5番目)に表示されているはずです。この「(あ)奥多摩温泉もえぎの湯」に、地図が表示されたときにinfowindowを立てることにします。
for (var i = 5; i <=5; i++)とします。
for (var i = 5; i <=5; i++) { var point = new google.maps.LatLng( parseFloat(markers[i].getAttribute("lat")), parseFloat(markers[i].getAttribute("lng"))); var name = markers[i].getAttribute("name"); var explanation = markers[i].getAttribute("explanation"); var category = markers[i].getAttribute("category"); var linkurl = markers[i].getAttribute("linkurl"); var html = '<div style="height: 150px; width: 200px"><b>'+name+'</b><br>'+explanation+'</b><br>'+linkurl+'</b>' + '<form action="http://maps.google.co.jp/maps" method="get" target="_blank">' + '<input value="ここへのルート検索" type="submit">' + '<input type="hidden" name="daddr" value="' + point.lat() + ',' + point.lng() + '"/>' ; createMarker(point,html,map,category,name); map.panTo(point); }
既存コードのどこに上記を挿入するかは、実際の下記サンプル地図のソースを眺めてみてください。
以上で完成です。(サンプルデモ)
完成させてから気がついたのですが、数百もマーカーがある場合、何番目の要素なのか数えるのが面倒でした。小さいことかもしれませんが。
下記第4項の「問題点他考察」の(4)を実現する必要がありそうです。
4.問題点他考察
(1)見かけ上は、地図が表示されると任意のマーカーのインフォウィンドウを最初から表示させることは出来るが、ナンか他にいい手があるはずである。
(2)配列が変わるような場合、この案は使えませんな。要素の番号で最初から表示させるインフォウィンドウを指定していますので、外部のXMLファイル等からマーカーデータを読み込んでいる場合は、注意が必要です。配列の順番が変われば、本来のマーカーではないアイコンにインフォウィンドウが開きます。マーカー(アイコン)を増やす場合は、XMLファイルの最後に追加することになります。
(3)この案では、一つの地図に一種類の外部jsファイルになるかと思いますので、共通のjsファイルが作れません。コードの共通部に変更が発生した場合、こんなソフトで全てのjsファイルを修正することになります。
(4)ナンか結局いい案が出来なかった。要はユーザが気がつかなければ何でもOKと考えると、別にマーカーを用意した方が手っ取り早いか?(サンプル)。 また、MySQLからマーカーデータを引っ張る場合にはどうしたらいいのだろうか。考えられるのは、例えば配列に「駅名」を割り当てておいて、要素に登録した「JR東京駅」「JR福島駅」「JR大阪駅」から、JR福島駅が要素の何番目にあるのかを検索して、その要素番号を個別にマーカーを表示させるための関数(function)にでも渡してやればいいのだろうか?出来るのか? 今回はここまで、時間切れ・・・・どこかにいい案がないだろうか(後日の宿題)
(5)外部XMLファイルからマーカーを読み込んでいる地図で本件用にソースを変更中に気がついたのが、infowindow.openのコマンド。projection_changedのイベントハンドラー内では、正常に動作しませんでした。後日、Googleのディスカッショングループでも覗いてみたいと思いますが・・・・(不具合?)。今回のソースでは、特に不要なのではずしましたが、createMarker()の関数だけを再度読み込む場合は、infowindouwが再び開いてしまうので、対策が必要ですね。(後日の宿題)
◆ Google Maps API v3 複数マーカーから特定のmarkerのインフォウィンドウ(infowindow)を最初から一つだけ表示するサンプルデモ
- (内部配列の場合)複数マーカーから特定のmarkerのインフォウィンドウ(infowindow)を最初から一つだけ表示するサンプル案(その1)
- (おまけ)複数マーカーから特定のmarkerのインフォウィンドウ(infowindow)を最初から一つだけ表示するサンプル案(その2)
- 外部XMLファイル読み出し+サイドバー地図でインフォウィンドウ(infowindow)を最初から一つだけ表示する
◆Google Maps JavaScript API V3
関連記事一覧
スポンサードリンク
サイドバーの記事でお世話になった えもん です。
とてもわかりやすい説明で、大変勉強になります!
お疲れ様です。
この記事のおかげでひらめきが生まれ、私の目的がひとまず達成できました。
私の場合、XMLから情報を取り出し、そのうちの一つをランダムで表示しようと考えていました。
createMarker() にインフォウィンドウを開く文があると、配列の最後のウィンドウが開くことに着目。
createMarker() の引数に、「for文の変数 i 」と「XMLデータの配列の長さ」を渡し、
if文で、「変数 i 」と「配列の長さから作った乱数」が一致した場合に、ウィンドウを開くようにしました。
この結果、ページを開くたびに違ったウィンドウを表示できるようになりました!
感謝申し上げます。
(2)についてはXMLの方で、開く要素の情報を持てば良いと思います。
で…
if( markers[i].getAttribute(“defaultopen”) ){ /*projection_changedイベントの登録等*/ }
あと…createMarker()の最後でopen処理をやっているのはあまり好きでないかも。マーカーを作成する度にinfoWindow.open()等を繰り返しているので、ちょっと重くなるはず。
createMarker()でreturn marker;して、返り値のMarkerオブジェクトに対してopen処理を行う。とか。