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 の落とし穴です。関数をループ内のイベント ハンドラーとしてインスタンス化し、関数がローカル変数を参照しています。問題は、それらすべてが同じローカル変数を参照していることです。つまり、同じ、単一、一意、メモリ内の 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」に「キャプチャ」されます。ループの反復ごとに無名関数が再度呼び出され、それが返す関数 (実際のハンドラー) は独自のプライベート "ii" 変数にアクセスできます。

同じことを達成する方法は他にもいくつかありますが、それらはすべてこのテーマのバリエーションにすぎません。

于 2011-01-29T14:30:15.417 に答える
0

イベントが特定のメーカーに登録されると、他のすべてのマーカーに対してもトリガーされるという同じ問題がありました。最後に、私はそれを解決することができました。マーカーごとに個別のイベントを登録する必要がありました。以下は私のコードです:

    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 に答える