2

我的地图上有标记层。

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

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自从添加了新标记后是否曾调用过该事件。如果确实调用了它,那么 remove 函数将什么也不做。

4

2 回答 2

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”变量。

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

于 2011-01-29T14:30:15.417 回答
0

我遇到了同样的问题,一旦将事件注册到特定的 Maker,它也会触发所有其他 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++;
    }

 }
}
于 2011-12-10T10:01:43.157 回答