簡體   English   中英

如何通過 leaflet 的按鈕單擊更改標記的圖標?

[英]How to change the icon of a marker through button click with leaflet?

我有一個帶有幾個標記的 map。 每個標記都有一個帶有 3 個按鈕的信息窗口,如下所示: 在此處輸入圖像描述

單擊每個按鈕時,都會更改標記的圖標。 但是,當我打開一個標記的信息窗口並且不單擊任何按鈕,go 到另一個標記並單擊其中一個按鈕時,兩個標記都會更改圖標,而不是僅更改最后一個單擊的圖標。 這是我的代碼:

//Get de todas as ignições presentes na base de dados
$.get("/api/IgnicoesAPI", function (data) {
  //alert(aceite)
  console.log(data);

  $.each(data, function (i, item) {
    //identificação do tipo de marcador que deve aparecer de acordo com o estado da ignição
    var ignicao;

    // MORE CODE

    var id = item.id;

    //colocar um marcador no mapa de acordo com a latitude e longitude fornecidas
    var marker = new L.marker([item.latitude, item.longitude], {
      icon: ignicao,
    })
      .on("click", function onClick(e) {
        //assim que um marcador for clicado é mostrado o popup das ignições
        modal.style.display = "block";

        //indicação do marcador que foi clicado
        clickedmarker = e.target;
        console.log(clickedmarker);

        //vai buscar toda a informação correspondente ao id fornecido
        getData(id);

        //Actividade dos botões presentes no popup das ignições
        $(document).on("click", "#aceite", function () {
          //se o estado for aceite, o botão respetivo estará desativado
          if (item.estado == aceite) {
            document.getElementById("aceite").disabled = true;
            document.getElementById("recusado").disabled = false;
            document.getElementById("concluido").disabled = false;
          }
          //se for clicado passará ao icon correspondente
          else {
            clickedmarker.setIcon(accepted);
            //fecha o modal das avaliação da ignição
            modal.style.display = "none";
            //atualiza a base de dados com o novo estado
            atualizaBD(id, Estado.aceite, item.latitude, item.longitude);
          }
        });

        $(document).on("click", "#concluido", function () {
          //se o estado for concluido, o botão respetivo estará desativado
          if (item.estado == concluido) {
            document.getElementById("concluido").disabled = true;
            document.getElementById("aceite").disabled = false;
            document.getElementById("recusado").disabled = false;
          }
          //se for clicado passará ao icon correspondente
          else {
            clickedmarker.setIcon(conclued);
            //fecha o modal das avaliação da ignição
            modal.style.display = "none";

            //atualiza a base de dados com o novo estado
            atualizaBD(id, Estado.concluido, item.latitude, item.longitude);
          }
        });

        $(document).on("click", "#recusado", function () {
          //se o estado for recusado, o marcador será removido do mapa
          //clickedmarker.removeFrom(map);

          //map.removeLayer(clickedmarker)

          map.removeLayer(marker);

          modal.style.display = "none";
          //atualiza a base de dados com o novo estado
          atualizaBD(id, Estado.recusado, item.latitude, item.longitude);
        });
      })
      .addTo(map);

    //adiciona marador ao mapa
    $("#json map").append(marker);

    if (item.estado == recusado) {
      map.removeLayer(marker);
    }
  }); // fim each
}); //fim do get

我應該如何解決這個問題?

這是一個關於關閉和附加事件處理程序過於急切的問題,這最終會使您的事件處理程序運行的次數超出您的預期。

在每個標記 click 上附加 jQuery 事件處理程序,所以如果您有類似...的代碼

var marker = new L.marker(/* stuff */).on("click", function onClick(ev) {
    $(document).on("click", "#aceite", function () {
        console.log('running click handler');
    });
});

...然后單擊標記,例如 10 次,其效果與附加 jQuery 單擊標記 10 次相同:

    $(document).on("click", "#aceite", function () {
        console.log('running click handler');
    });
    $(document).on("click", "#aceite", function () {
        console.log('running click handler');
    });
    $(document).on("click", "#aceite", function () {
        console.log('running click handler');
    });
    $(document).on("click", "#aceite", function () {
        console.log('running click handler');
    });
    $(document).on("click", "#aceite", function () {
        console.log('running click handler');
    });
    $(document).on("click", "#aceite", function () {
        console.log('running click handler');
    });
    $(document).on("click", "#aceite", function () {
        console.log('running click handler');
    });
    $(document).on("click", "#aceite", function () {
        console.log('running click handler');
    });
    $(document).on("click", "#aceite", function () {
        console.log('running click handler');
    });
    $(document).on("click", "#aceite", function () {
        console.log('running click handler');
    });

因此,如果您隨后單擊該按鈕一次,代碼將運行 10 次。

您會感到困惑,因為id存在於循環的 scope 中,並且 jQuery 點擊處理程序 function 是在所述循環中定義的。 因此,如果我們暫時假設您有 ID 為 4 和 5 的項目,並且您在代碼上的每個項目的每個標記上單擊一次...

$.each(數據, function (i, item) { var id = item.id;

var marker = new L.marker(/* stuff */).on("click", function onClick(ev) {
    $(document).on("click", "#aceite", function () {
        console.log('running click handler with ID', id);
    });
});

...這相當於附加兩個不同的單擊事件處理程序,每個處理程序都有不同的閉包值(因為它們位於不同的范圍內):

    $(document).on("click", "#aceite", function () {
        console.log('running click handler with ID', 4);
    });        
    $(document).on("click", "#aceite", function () {
        console.log('running click handler with ID', 5);
    });

因此,如果您隨后單擊該按鈕一次,代碼將運行兩次。

除非您真的確定自己在做什么(即您正在跟蹤有多少事件處理程序附加到一個事件並根據需要將它們分離),否則請避免在循環內和其他事件處理程序內附加事件處理程序。

所以,而不是...

data.forEach(function (item, i) {
    var id = item.id;
    L.marker(item.latlng).on('click', function(ev) {
        $("#button").on('click', function() {
            console.log('Doing stuff for item', id);
        });
    });
});

...您應該嘗試保持應該運行一次的事情(即附加 jQuery 事件處理程序)運行一次,並將任何需要的 state 提升到一個常見的 scope,例如 ...

// 'id' exists out of the scope of any functions defined inside the loop,
// so it ""exists only once"" to the eyes of those functions
var id;    

data.forEach(function (item, i) {
    L.marker(item.latlng).on('click', function(ev) {
        // Since the marker click handler function is defined within a loop,
        // and the scope of 'item' is that of the loop, it forms a closure, 
        // which means it's ""unique"" to each of the marker click handler
        // functions.
        // By contrast, 'id' is defined outside of that scope, so it's
        // ""common"" to all of the marker click handler functions
        id = item.id;
    });
}); 

// Attach the jQuery event handler **once**, and do not wait
// until clicking on a marker to do so.
$("#button").on('click', function() {
    console.log('Doing stuff for item', id);
});

請閱讀閉包 真的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM