Подтвердить что ты не робот

API Карт Google v3 добавляет InfoWindow к каждому маркеру

ПРИМЕЧАНИЕ. Я использую 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, но я не постингирую. Любые идеи?

4b9b3361

Ответ 1

У вас очень распространенная проблема закрытия в цикле 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, а затем открыть его и изменить его содержимое всякий раз, когда щелкнет маркер (Источник).

Ответ 2

Вы можете использовать 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.
});

Ответ 3

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

Ответ 5

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

My for loops теперь:

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

Ответ 6

для 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);
            });
        }

Ответ 7

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

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

Ответ 8

Попробуйте следующее:

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

Ответ 9

У меня была очень похожая проблема, но в ActionScript 3: Stack Over Flow: динамическое окно API-интерфейса API Карт Google Проблема с HTML-контентом

Я пытался извлечь уникальную информацию в htmlcontent всплывающих подсказок из базы данных и обнаружил, что получаю информацию о последнем маркере, который я добавил в каждом маркере.

Предполагая, что это не специфическая проблема с ActionScript, решение JochenJung не будет работать. Посмотрите на решение, которое я разместил в своей проблеме, и посмотрим, можете ли вы применить его здесь. Это похоже на серьезную проблему с API карт.

Ответ 10

Единственный способ, с помощью которого я мог бы заставить это работать, - создать массив в JavaScript. Элементы массива ссылаются на различные инфо-окна (для каждого маркера на карте создается одно информационное окно). Каждый элемент массива содержит уникальный текст для соответствующего маркера карты. Я определил событие 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);
    });
}

Ответ 11

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