【问题标题】:Listener event always triggers with last element's info侦听器事件总是使用最后一个元素的信息触发
【发布时间】:2013-01-15 00:01:24
【问题描述】:

我正在尝试制作基于地图的应用程序,但遇到了一些困难。我一直在使用的原始代码为每个标记添加了一个单独的 InfoWindow,但我想使用一个可以动态设置内容的 InfoWindow 来获取它。

但是,我对 JavaScript 的行为方式似乎仍然有些模糊,因为每次单击任何标记时,信息窗口都会在最后一个标记上弹出,并且警报会指示 locations 中最后一个条目的 ID。

短sn-p,问题突出:

function plotLocations(my_locations) {
    locations = my_locations;
    for(var i=0; i<locations.length; i++) {
        var pos = new google.maps.LatLng(locations[i].loc_lat, locations[i].loc_lng);
        var icon = new google.maps.MarkerImage(
            "http://goo.gl/TQpwU",
            new google.maps.Size(20,32),
            new google.maps.Point(0,0),
            new google.maps.Point(0,32)
        );
        var marker = new google.maps.Marker({
            map: map,
            position: pos,
            animation: google.maps.Animation.DROP,
            icon: icon
        });
// ! -- trouble right here -- ! //
        google.maps.event.addListener(marker, 'click', function() {
            setPopInfo(pos, i);
        });
// ! -- ------------------ -- ! //
    }
}

function setPopInfo(pos, index) {
    pop_info.setPosition(pos);
    pop_info.open(map);
    window.alert(pos+"::"+index);
}

我的大部分代码:

var map;
var mapBounds;
var locations;
var pop_info;

$(document).ready(init);

function init() {
    var mapOptions = {
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
    pop_info = new google.maps.InfoWindow({
        content: "I'm not populated!",
        size: new google.maps.Size(100,25)
    });
    google.maps.event.addListener(map, 'bounds_changed', function() {
        queryLocations(map.getBounds());
    });

    prepareGeolocation();
    doGeolocation();
}

function queryLocations(bounds) {
    jQuery.ajax({
        url: 'http://mydomain.com/myapp/test2.php',
        data: bounds.toString(),
        dataType: 'json',
        success: addLocations
    });
}

function addLocations(new_locations) {
    document.getElementById('footer').innerHTML = new_locations;
    plotLocations(new_locations);
}

我对单个 InfoWindow 的推理是,一旦创建了数百个标记和 InfoWindow,性能可能会急剧下降。我正在尝试做的事情是否可行/可取?

【问题讨论】:

  • Multiple Google Maps infowindow 的可能重复项
  • 不,过早的优化是没有意义的,尤其是如果它破坏了你的代码!
  • @Fraser 如果我称之为“设计决策”会怎样? :D
  • @Sammitch 我会笑说这是一个糟糕的设计决定 - stackoverflow.com/questions/385506/…
  • @Fraser 但我并不想通过寻找“更高效”的循环/逻辑/字符串/等构造来减少 3 个 CPU 周期,而是避免创建数十个/数百个不必要的最终可能包含数千字节数据的对象。除了我对 Javascript 的缺乏经验之外,当我看到它时我就知道代码很糟糕,而且我修复的代码很糟糕,将来会出现问题。

标签: javascript google-maps


【解决方案1】:

出现问题是因为您在循环内定义了事件侦听器回调函数。闭包动态引用它们的上下文,而不是在定义时绑定到数据的副本,因此您有效地创建了 locations.length 数量的函数,这些函数都绑定到 markerpos 和 @ 的相同值987654324@,这是循环终止时发生的任何事情。

要解决这个问题,您可以创建一个在循环体外部调用 addListener 的函数,如下所示:

function plotLocations (my_locations) {
    locations = my_locations;
    for(var i=0; i<locations.length; i++) {
        var pos = new google.maps.LatLng(locations[i].loc_lat, locations[i].loc_lng);
        var icon = new google.maps.MarkerImage(
            "http://goo.gl/TQpwU",
            new google.maps.Size(20,32),
            new google.maps.Point(0,0),
            new google.maps.Point(0,32)
        );
        var marker = new google.maps.Marker({
            map: map,
            position: pos,
            animation: google.maps.Animation.DROP,
            icon: icon
        });
        bindEvent(marker, pos, i);
    }
}

function bindEvent (marker, pos, i) {
    google.maps.event.addListener(marker, 'click', function() {
        setPopInfo(pos, i);
    });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-05
    • 2015-12-30
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 2020-09-06
    • 2018-04-04
    • 2015-12-18
    相关资源
    最近更新 更多