注:Google Maps APIのv3を使用しています
マップに配置した各マーカーに情報ウィンドウを追加しようとしています。現在、私はこれを次のコードで行っています:
for (var i in tracks[racer_id].data.points) {
values = tracks[racer_id].data.points[i];
point = new google.maps.LatLng(values.lat, values.lng);
if (values.qst) {
var marker = new google.maps.Marker({map: map, position: point, clickable: true});
tracks[racer_id].markers[i] = marker;
var info = new google.maps.InfoWindow({
content: '<b>Speed:</b> ' + values.inst + ' knots'
});
tracks[racer_id].info[i] = info;
google.maps.event.addListener(marker, 'click', function() {
info.open(map, marker);
});
}
track_coordinates.Push(point);
bd.extend(point);
}
問題は、マーカーをクリックすると、最後に追加されたマーカーの情報ウィンドウが表示されることです。また、明確にするために、クリックされたマーカーではなく、最後のマーカーの横に情報ウィンドウが表示されます。私の問題はaddListenerの部分にあると思いますが、それはポジティブではありません。何か案は?
for in
ループで 非常に一般的なクロージャの問題 が発生しています:
クロージャに囲まれた変数は同じ単一の環境を共有するため、click
からのaddListener
コールバックが呼び出されるまでに、ループはそのコースを実行し、info
変数は最後に作成されたInfoWindow
である最後のオブジェクトを指すようになります。
この場合、この問題を解決する簡単な方法の1つは、Marker
オブジェクトにInfoWindow
を追加することです。
var marker = new google.maps.Marker({map: map, position: point, clickable: true});
marker.info = new google.maps.InfoWindow({
content: '<b>Speed:</b> ' + values.inst + ' knots'
});
google.maps.event.addListener(marker, 'click', function() {
marker.info.open(map, marker);
});
クロージャーがどのように機能するかをよく知らない場合、これは非常に難しいトピックになります。簡単な紹介については、次のMozillaの記事をご覧ください。
また、v3 APIはマップ上で複数のInfoWindow
sを許可することに注意してください。 InfoWindow
を一度に1つだけ表示する場合は、代わりに単一のInfoWindow
オブジェクトを使用し、マーカーがクリックされるたびにそのオブジェクトを開いてその内容を変更する必要があります( ソース )。
イベントでthis
を使用できます:
google.maps.event.addListener(marker, 'click', function() {
// this = marker
var marker_map = this.getMap();
this.info.open(marker_map);
// this.info.open(marker_map, this);
// Note: If you call open() without passing a marker, the InfoWindow will use the position specified upon construction through the InfoWindowOptions object literal.
});
Add_markerにはまだクロージャーの問題があります。これは、google.maps.event.addListenerスコープ外のマーカー変数を使用するためです。
より良い実装は次のとおりです。
function add_marker(racer_id, point, note) {
var marker = new google.maps.Marker({map: map, position: point, clickable: true});
marker.note = note;
google.maps.event.addListener(marker, 'click', function() {
info_window.content = this.note;
info_window.open(this.getMap(), this);
});
return marker;
}
また、マーカーからマップを使用しました。この方法では、Googleマップオブジェクトを渡す必要はありません。おそらく、マーカーが属するマップを使用する必要があります。
こんにちは、みなさん。これが最適なソリューションであるかどうかはわかりませんが、将来的に人々を助けるためにここに投稿すると思いました。変更する必要がある場合はコメントしてください。
私のforループは次のとおりです。
for (var i in tracks[racer_id].data.points) {
values = tracks[racer_id].data.points[i];
point = new google.maps.LatLng(values.lat, values.lng);
if (values.qst) {
tracks[racer_id].markers[i] = add_marker(racer_id, point, '<b>Speed:</b> ' + values.inst + ' knots<br /><b>Invalid:</b> <input type="button" value="Yes" /> <input type="button" value="No" />');
}
track_coordinates.Push(point);
bd.extend(point);
}
そして、add_marker
と定義されている:
var info_window = new google.maps.InfoWindow({content: ''});
function add_marker(racer_id, point, note) {
var marker = new google.maps.Marker({map: map, position: point, clickable: true});
marker.note = note;
google.maps.event.addListener(marker, 'click', function() {
info_window.content = marker.note;
info_window.open(map, marker);
});
return marker;
}
Info_window.close()を使用して、いつでもinfo_windowをオフにすることができます。これが誰かを助けることを願っています。
earthプラグインAPIの場合、ループの外にバルーンを作成し、カウンターを関数に渡して、各目印の一意のコンテンツを取得します。
function createBalloon(placemark, i, event) {
var p = placemark;
var j = i;
google.earth.addEventListener(p, 'click', function (event) {
// prevent the default balloon from popping up
event.preventDefault();
var balloon = ge.createHtmlStringBalloon('');
balloon.setFeature(event.getTarget());
balloon.setContentString('iframePath#' + j);
ge.setBalloon(balloon);
});
}
私の場合(Razor内でJavaScriptを使用)これはForeachループ内で完全に機能しました
google.maps.event.addListener(marker, 'click', function() {
marker.info.open(map, this);
});
同様の問題がありました。マーカーをクリックするのではなく、マーカーの上にマウスを移動したときに情報を表示するだけでよい場合は、情報ウィンドウを使用する代わりにマーカーにタイトルを設定することをお勧めします。そのようにすると、マーカーの上にマウスを置くと、タイトルがALTタグのように表示されます。 'marker.setTitle(' Marker '+ id);'マーカーのリスナーを作成する必要もなくなります
最終的にこれを機能させる唯一の方法は、JavaScriptで配列を作成することでした。配列要素は、さまざまな情報ウィンドウを参照します(地図上のマーカーごとに1つの情報ウィンドウが作成されます)。各配列要素には、適切なマップマーカーの一意のテキストが含まれています。配列要素に基づいて、各情報ウィンドウのJavaScriptイベントを定義しました。イベントが発生すると、「this」キーワードを使用して配列要素を参照し、表示する適切な値を参照します。
var map = new google.maps.Map(document.getElementById('map-div'), mapOptions);
zipcircle = [];
for (var Zip in zipmap) {
var circleoptions = {
strokeOpacity: 0.8,
strokeWeight: 1,
fillOpacity: 0.35,
map: map,
center: zipmap[Zip].center,
radius: 100
};
zipcircle[zipmap[Zip].zipkey] = new google.maps.Circle(circleoptions);
zipcircle[zipmap[Zip].zipkey].infowindowtext = zipmap[Zip].popuptext;
zipcircle[zipmap[Zip].zipkey].infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(zipcircle[zipmap[Zip].zipkey], 'click', function() {
this.infowindow.setContent(this.infowindowtext);
this.infowindow.open(map, this);
});
}
これを試して:
for (var i in tracks[racer_id].data.points) {
values = tracks[racer_id].data.points[i];
point = new google.maps.LatLng(values.lat, values.lng);
if (values.qst) {
var marker = new google.maps.Marker({map: map, position: point, clickable: true});
tracks[racer_id].markers[i] = marker;
var info = new google.maps.InfoWindow({
content: '<b>Speed:</b> ' + values.inst + ' knots'
});
tracks[racer_id].info[i] = info;
google.maps.event.addListener(tracks[racer_id].markers[i], 'click', function() {
tracks[racer_id].info[i].open(map, tracks[racer_id].markers[i]);
});
}
track_coordinates.Push(point);
bd.extend(point);
}