Google Maps API v3, добавляющий InfoWindow к каждому маркеру - PullRequest
44 голосов
/ 01 июля 2010

ПРИМЕЧАНИЕ. Я использую v3 API Карт Google

Я пытаюсь добавить информационное окно для каждого маркера, который я поместил на карту.В настоящее время я делаю это с помощью следующего кода:

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, но я не являюсь положительным.Есть идеи?

Ответы [ 9 ]

79 голосов
/ 01 июля 2010

У вас очень распространенная проблема закрытия в цикле for in:

Переменные, заключенные в замыкание, совместно используют одну и ту же среду, поэтому к тому времени, когда будет вызван обратный вызов click из addListener, цикл будет работать, а переменная info будет указывать на последний объект, который оказывается последним InfoWindow созданным.

В этом случае одним из простых способов решения этой проблемы было бы увеличение объекта 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 для краткого введения:

Также имейте в виду, что API v3 позволяет использовать несколько InfoWindow на карте. Если вы хотите, чтобы в данный момент был виден только один InfoWindow, вместо этого следует использовать один объект InfoWindow, а затем открывать его и изменять его содержимое при каждом щелчке маркера ( Source ).

35 голосов
/ 18 мая 2013

Вы можете использовать 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.
});
9 голосов
/ 27 июля 2012

У 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, вы, вероятно, хотите использовать карту, которой в любом случае принадлежит маркер.

1 голос
/ 29 июня 2017

В моем случае (с использованием Javascript insidde Razor) Это прекрасно работало внутри цикла Foreach

google.maps.event.addListener(marker, 'click', function() {
    marker.info.open(map, this);
});
1 голос
/ 06 апреля 2013

для API плагинов Earth, создайте выноску вне цикла и передайте свой счетчик в функцию, чтобы получить уникальное содержимое для каждой метки!

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 голос
/ 01 июля 2010

Привет всем. Я не знаю, является ли это оптимальным решением, но я решил опубликовать его здесь, чтобы надеяться помочь людям в будущем. Пожалуйста, прокомментируйте, если вы видите что-то, что должно быть изменено.

Мой цикл теперь:

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 в любое время. Надеюсь, это кому-нибудь поможет.

0 голосов
/ 22 мая 2015

У меня была похожая проблема. Если все, что вам нужно, это чтобы какая-то информация отображалась при наведении курсора на маркер, вместо того, чтобы щелкать по нему, то я обнаружил, что хорошей альтернативой использованию информационного окна является установка заголовка на маркер. Таким образом, когда вы наводите курсор мыши на маркер, заголовок отображается как тэг ALT. 'marker.setTitle (' Marker '+ id);' Это избавляет от необходимости создавать слушателя для маркера тоже

0 голосов
/ 30 мая 2014

Единственный способ, которым я наконец смог заставить это работать, - это создание массива в JavaScript.Элементы массива ссылаются на различные информационные окна (для каждого маркера на карте создается одно информационное окно).Каждый элемент массива содержит уникальный текст для соответствующего маркера карты.Я определил событие JavaScript для каждого информационного окна на основе элемента массива.И когда событие запускается, я использую ключевое слово this для ссылки на элемент массива, чтобы указать соответствующее значение для отображения.

0 голосов
/ 01 июля 2010

Попробуйте это:

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...