2011-01-29 16 views
2

Hey。 マップ上にマーカーレイヤーがあります。OpenLayerのマーカーイベントの異常な動作

私はマウスクリックイベントに私はそれを登録し、新しいマーカーを追加するたび:

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が開きます。

誰かが私を助けることができますか?

注:理由は、新しいマーカーが追加されて以来、DisableAllmMarkersが呼び出されたかどうかわからないため、EnableAllmMarkersは最初にイベントを削除します。実際に呼び出された場合、remove関数は何もしません。

答えて

7

これは古典的なJavaScriptトラップです。ループ内のイベントハンドラとして関数をインスタンス化しており、その関数はローカル変数を参照しています。問題は、すべて同じローカル変数を参照しているということです:同じ、単一の、ユニークな、ただ1つのメモリ内の変数。この場合の変数は「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"に "捕捉"されます。各ループの反復では、匿名関数の別の呼び出しが行われ、それが返す関数(実際のハンドラ)は自身のprivate "ii"変数にアクセスします。

同じことを達成するためのいくつかの方法がありますが、すべてこのテーマのバリエーションです。

+0

ありがとう、私はそれをチェックします。 「別問題」で何を意味しましたか? –

+0

ああ、実際の配列(整数で索引付けされている)を持っているなら、for(var i in array)ではなくfor(var i = 0; i Pointy

+0

私はあなたの提案されたコードで試しましたが、今では、マーカーをクリックすることなく何度も何度もイベントハンドラが呼び出されます。 –

0

私は同じ問題を抱えていました。イベントが特定のMakerに登録されると、他のすべてのマーカーもトリガーされました。最後に、私はそれを解決することができました。私は各マーカーに別々の出来事を登録しなければならなかった。以下は私のコードです:

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

} 
} 
+0

誰かが同じ問題を抱えている場合。単に "icon"の代わりに "icon.clone()"を使用すると、私のためにそれを修正しました。 –

関連する問題