2008年10月20日

forループの中でGevent.addListenerを使う

livedoorClipに登録 | このエントリーをはてなブックマークに追加 | del.icio.usに登録 | MM/Memoに登録

思ったとおりに動いてくれない

forループ内で読んだGEvent.addListenerが意図した動作をしてくれない。
症状とコードは下記の通り。

  • マーカーは作られる
  • しかし、どのマーカーをクリックしても同一マーカーから情報窓が出てくる
for (var i = 0; i< loaddata.data.length; i++) {
  var point  = new GLatLng(data[i].lat, data[i].lng);
  var marker = new GMarker(point);
  GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowHtml("Marker #" + i);
  });
  map.addOverlay(marker);
}

※dataは連想配列の配列とする



解決策はクロージャにあり

検索してみたけど、同じ現象を解決したエントリを見つけられなかった。
APIのドキュメントを読んでいたら解決策を見つけた。

イベントクロージャより

イベント リスナでクロージャを使用する

イベント リスナを実行するときは、オブジェクトにプライベート データと永続データの両方を添付することが一般に有効です。JavaScript は「プライベート」インスタンスデータをサポートしていませんが、内部関数が外部変数にアクセスすることを可能にするクロージャ をサポートしています。イベントリスナ内でクロージャを使用すると、イベントが発生したオブジェクトには通常添付されていない変数にアクセスできるので便利です。

次の例では、イベント リスナ内で関数クロージャを使用して、一連のマーカーにシーケンス番号値を割り当てています。各マーカーをクリックすると、そのマーカー自体には含まれていない個別の値が表示されます。

なるほど…

function createMarker(point, number) {
  var marker = new GMarker(point);
  GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowHtml("Marker #" + number);
  });
  return marker;
}

for(var i = 0; i< loaddata.data.length; i++) {
  var point  = new GLatLng(data[i].lat, data[i].lng);
  map.addOverlay(createMarker(point, i));
}

これで無事に解決した



Google Maps Hacks 第2版 ―地図検索サービスをもっと活用するテクニック
Rich Gibson Schuyler Erle
オライリー・ジャパン
売り上げランキング: 49910


半袖 at 17:25│Comments(1)TrackBack(0)Google Maps 

トラックバックURL

この記事へのコメント

1. Posted by しげる   2009年05月15日 17:41
参考になりました。ありがとうございます。
僕の場合はデータベースとマーカーマネージャの使用を考えてこんな感じになりました。
(markerIconはGIconのインスタンス)

function createMarker(point, record) {
var marker = new GMarker(point, {icon:markerIcon});
GEvent.addListener(marker, "click", function(){
marker.openInfoWindowHtml(record.title+"<br/>"+record.date);
});
return marker;
}

for (var i in db) {
var record = db[i];
var point = new GLatLng(record.lat, record.lng);
manager.addMarker(createMarker(point, record), record.minZoom);
}

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔