リーフレットのマーカーにイベントリスナーを追加する


10

私はマップをレンダリングするためにリーフレットを使用しています。マーカー付きのマップを作成しましたが、各マーカーにイベントリスナー「onClick」を実装する方法がわかりません。

私のコード

var stops = JSON.parse(json);
var map = new L.Map('map', {
  zoom: 12,
  minZoom: 12,
  center: L.latLng(41.11714, 16.87187)
});
map.addLayer(L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
  attribution: 'Map data',
  maxZoom: 18,
  id: 'mapbox.streets',
  accessToken: '-----'
}));
var markersLayer = new L.LayerGroup();
map.addLayer(markersLayer);


//populate map from stops
for (var i in stops) {
  L.marker(L.latLng(stops[i].Position.Lat, stops[i].Position.Lon), {
    title: stops[i].Description
  }).addTo(markersLayer).bindPopup("<b>" + stops[i].Description + "</b>").openPopup();
}

map.on('click', function(e) {
    alert(e.latlng);
});

リーフレットは参照によってイベントリスナーを処理するため、リスナーを追加してから削除する場合は、関数として定義します。

function onClick(e) { ... }

map.on('click', onClick);
map.off('click', onClick);

TimoSperisenさんへの答え@を参照してくださいこの質問彼は掲載フィドルそれは私の作品
Mawgはモニカ回復言う

回答:


14

GIS Stack Exchangeへようこそ!

マーカーのクリックイベントにコールバックをアタッチするのに特別な問題はないはずです。myMarker.on('click', callback)マップで行ったように使用するだけです。また、コールバックをアタッチするすべてのマーカーについても、これを行う必要があります。

もう1つの可能性は、すべてのマーカーを機能グループに追加することです(たとえばmarkersLayer、のL.featureGroup()代わりにでインスタンス化するL.layerGroup())。そのグループにコールバックを直接アタッチできます。個々のマーカーからクリックイベントを受け取り、を使用して個々のクリックされた機能にアクセスできますevent.layer

var markersLayer = L.featureGroup().addTo(map);

// populate map from stops…

markersLayer.on("click", function (event) {
    var clickedMarker = event.layer;
    // do some stuff…
});

デモ:http : //jsfiddle.net/ve2huzxw/74/

Leafletフォーラムで他の人が尋ねた同様の質問:https ://groups.google.com/forum/#!topic/leaflet-js/ RDTCHuLvMdw


追加するだけevent.layer.propertiesで、GeoJSON形式に従って、マーカーのすべてのプロパティ(メタデータ)の配列にアクセスできます。したがってevent.layer.properties.description = stops[i].Description、たとえば割り当てることができます。
Nikhil VJ 2018

4

マップの人口ループを変更して、マーカーにプロパティを割り当てます。

//populate map from stops
for (var i in stops) {
  var oneMarker = L.marker(L.latLng(stops[i].Position.Lat, stops[i].Position.Lon), {
    title: stops[i].Description
  }).bindPopup("<b>" + stops[i].Description + "</b>").openPopup();

  oneMarker.properies.name = stops[i].Name;
  oneMarker.properies.description = stops[i].Description;
  oneMarker.properies.othervars = stops[i].othervars;
  oneMarker.addTo(markersLayer);
}

後で、onclickイベントでこれらのプロパティ(呼び出されたとおりの機能プロパティ)にアクセスするには、

markersLayer.on("click", markerOnClick);

function markerOnClick(e) {
  var attributes = e.layer.properties;
  console.log(attributes.name, attributes.desctiption, attributes.othervars);
  // do some stuff…
}

このproperties.varアプローチには、マーカーを標準のGeoJson形式にするという追加の利点があります。たとえば、データをシェープファイルとしてエクスポートしたり、マーカーをシェープファイルからインポートしたりする必要がある場合に、互換性を確保します。


1
私はあなたの提案を私自身のセットアップに取り入れようとしています。しかし、単純なoneMarker.propertiesを追加すると、「oneMarker.properties is undefined」というエラーメッセージが表示されます。私は明らかな何かを見落としている?? よろしくお願いします。例コードのプロパティ........ propertiesのスペルを間違えました
アレックス

1
ああ、私は解決策を見つけたと思います:oneMarker.properties = {};を追加する必要がありました。btw:var oneMarkerを使用するのは正しいですか、これは動的な名前にする必要がありますか?
アレックス

プロパティハックについて知っておくと良い@alex。はい、使用var oneMarkerしても問題ありません。これはforループ内のローカルスコープであり、layer.addTo()行で値が追加されます。(例:配列への参照ではなく、配列にa=3; array1.push[a];3を追加しますa。)
Nikhil VJ

0

リーフレットマップオブジェクト内でクリック可能なマーカーの配列を作成するかなり簡単で簡単な方法は、カスタムのインクリメントされたクラス名を各マーカーに追加して、作成されたマーカーのクラスリストを操作することです。その後、リスナーを作成して、どのマーカーがクリックされたかを知るのは簡単です。アクティブなものをスキップするかどうかにかかわらず、それぞれに、信頼できるIDを持つ取得可能なクリックイベントがあります。

  // creates markers, each with a leaflet supplied class
  if (length === 1) {
    for (i = 0; i < parks.length; ++i) {
      if (parks[i].parksNumber !== parks.parksNumber)
        L.marker([parks[i].latitude, parks[i].longitude], {
          icon: parks[i].iconMarker
        }).addTo(mymap);
    }
  }

  // select all of the leaflet supplied class
  let markers = document.querySelectorAll(".leaflet-marker-icon");

  // loop through those elements and first assign the indexed custom class
  for (i = 0; i < markers.length; ++i) {
    markers[i].classList.add("marker_" + parks[i].parksNumber);

    // then add a click listener to each one
    markers[i].addEventListener("click", e => {

      // pull the class list
      let id = String(e.target.classList);

      // pull your unique ID from the list, be careful cause this list could 
      // change orientation,  if so loop through and find it
      let parksNumber = id.split(" ");
      parksNumber = parksNumber[parksNumber.length - 1].replace("marker_", "");

      // you have your unique identifier to then do what you want with
      search_Number_input.value = parksNumber;
      HandleSearch();
    });
  }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.