OpenLayer中标记事件的奇怪行为

时间:2011-01-29 13:37:38

标签: javascript events javascript-events openlayers markers

嘿。 我的地图上有标记图层。

每次添加新标记时,我都会将其注册到鼠标单击事件:

var lonlat = new OpenLayers.LonLat(lon,lat);
var marker = new OpenLayers.Marker(lonlat,icon);
marker.id = callId;

marker.events.register("mousedown", marker, function() {AddPopup(marker.id);});

callMarkers.addMarker(marker);

有时我想禁用/启用该事件。所以我使用这些功能:

function EnableAllMarkers()
{ 
    for (var i in callMarkers.markers)
    {
        callMarkers.markers[i].events.remove("mousedown");               

        callMarkers.markers[i].events.register("mousedown", callMarkers.markers[i],   

        function() { AddPopup(callMarkers.markers[i].id); });
    }  
}


function DisableAllMarkers()
{ 
    for (var i in callMarkers.markers)
    {
        callMarkers.markers[i].events.remove("mousedown");
    }  
}

当我使用这段代码时,我会遇到奇怪的行为 - 有时会弹出错误标记的弹出窗口。   我点击标记X并弹出Y打开。

有人可以帮助我吗?

请注意: EnableAllmMarkers首先删除事件的原因是因为我们不知道自添加新标记以来是否曾调用过DisableAllmMarkers。如果它确实被调用,删除函数将不执行任何操作。

2 个答案:

答案 0 :(得分:7)

这是一个经典的JavaScript陷阱:您在循环中将函数实例化为事件处理程序,并且函数引用局部变量。问题是所有都引用了相同的局部变量:相同的,唯一的,唯一的,只有一个位置的内存变量。在这种情况下,变量是“i”。

for循环结束时,“i”将拥有对象中最后一个键的值(顺便说一下,如果callMarkers.markers实际上是一个数组,那么这个应该是无论如何都不是for ... in循环,但这是一个单独的问题)。因此,当这些事件最终触发时,所有处理程序都将使用“i”等于同一个键来执行它们的操作。

修复:

  for (var i in callMarkers.markers)
    {
        callMarkers.markers[i].events.remove("mousedown");               

        callMarkers.markers[i].events.register(
          "mousedown", 
          callMarkers.markers[i],
          (function(ii) {
            return function() {
              AddPopup(callMarkers.markers[ii].id);
            }
          )(i)
         );
    } 

这引入了一个中间匿名函数。该函数立即被调用,并传递当前值“i”。通过这样做 - 将“i”作为参数传递给匿名函数 - 该值在参数“ii”中被“捕获”。每次循环迭代都将导致匿名函数的另一次调用,它返回的函数(实际处理程序)将可以访问自己的私有“ii”变量。

还有其他一些方法可以实现同样的目标,但它们只是这个主题的变体。

答案 1 :(得分:0)

我有同样的问题,一旦事件被注册到特定的制作者,它也会触发所有其他Marker。最后,我能够解决它。我必须为每个标记注册单独的事件。以下是我的代码:

    var makerCount=0; // I want only 2 Markers to be shown : Source,Destination

function setMarkers(x,y){
    var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png',size,offset);  

 if(makerCount<2){

    if(makerCount==0){  // Source
       var location = new OpenLayers.LonLat(x,y); 

       var size = new OpenLayers.Size(21,25);
       var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);

        var sourceMarker=new OpenLayers.Marker(location,icon)
        sourceMarker.events.register('mousedown', sourceMarker, function(evt) { 
                alert('Source :: X='+ x + ' , Y=' + y); 
                OpenLayers.Event.stop(evt); }); 


        markers.addMarker(sourceMarker); 
        markers.setOpacity(0.2);
        makerCount++;
    }else{ // Destination

        var location = new OpenLayers.LonLat(x,y); 

        var size = new OpenLayers.Size(21,25);
        var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
        var halfIcon = icon.clone();  

        var destinationMarker=new OpenLayers.Marker(location,halfIcon)
        destinationMarker.events.register('mousedown', destinationMarker, function(evt) { 
                alert('Destination :: X='+ x + ' , Y=' + y); 
                OpenLayers.Event.stop(evt); 
           });          
        markers.addMarker(destinationMarker); 
        halfIcon.setOpacity(0.5);
        makerCount++;
    }

 }
}