web-dev-qa-db-ja.com

各マーカーに情報ウィンドウを追加するGoogle Maps API v3

注: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の部分にあると思いますが、それはポジティブではありません。何か案は?

44
blcArmadillo

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はマップ上で複数のInfoWindowsを許可することに注意してください。 InfoWindowを一度に1つだけ表示する場合は、代わりに単一のInfoWindowオブジェクトを使用し、マーカーがクリックされるたびにそのオブジェクトを開いてその内容を変更する必要があります( ソース )。

79
Daniel Vassallo

イベントで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.
});
35
ostapische

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マップオブジェクトを渡す必要はありません。おそらく、マーカーが属するマップを使用する必要があります。

9
ceasaro

こんにちは、みなさん。これが最適なソリューションであるかどうかはわかりませんが、将来的に人々を助けるためにここに投稿すると思いました。変更する必要がある場合はコメントしてください。

私の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をオフにすることができます。これが誰かを助けることを願っています。

1
blcArmadillo

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);
            });
        }
1
Al-Chalabee

私の場合(Razor内でJavaScriptを使用)これはForeachループ内で完全に機能しました

google.maps.event.addListener(marker, 'click', function() {
    marker.info.open(map, this);
});
1
Rhibi Hamza

同様の問題がありました。マーカーをクリックするのではなく、マーカーの上にマウスを移動したときに情報を表示するだけでよい場合は、情報ウィンドウを使用する代わりにマーカーにタイトルを設定することをお勧めします。そのようにすると、マーカーの上にマウスを置くと、タイトルがALTタグのように表示されます。 'marker.setTitle(' Marker '+ id);'マーカーのリスナーを作成する必要もなくなります

0
cormacio100

最終的にこれを機能させる唯一の方法は、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);
    });
}
0
John Doe

これを試して:

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);
}
0
JochenJung