web-dev-qa-db-ja.com

リーフレットのマーカーにIDを割り当てる

だから私はfoursquareのように結果を達成しようとします: https://foursquare.com/explore?cat=drinks&mode=url&near=Paris 地図上のマーカーをクリックすると、画面の右側にあるレストランのリストをスクロールして、アドホックレストランに移動し、CSSで強調表示します。逆に、リスト上のレストランをクリックすると、地図上でそのレストランが強調表示されます。

Skobbler /リーフレットを使用しています。この例に示すようにCSSを動的に修正することでこれを達成できると思います: http://jsfiddle.net/gU4sw/7/ +スクロールして宛先スクリプトは既にページに配置されています。

ただし、これを実現するには、マーカー内にIDを割り当てる必要があるようです(下の2つのマーカー)。

var marker = L.marker([52.52112, 13.40554]).addTo(map);
marker.bindPopup("Hello world!<br>I am a popup1.", { offset: new L.Point(-1, -41) }).openPopup();

var marker = L.marker([52.53552, 13.41994]).addTo(map);
marker.bindPopup("Hello world!<br>I am a popup2.", { offset: new L.Point(-1, -41) }).openPopup();

質問:マーカーIDを割り当てて、HTMLページ内の対応する要素でCSSの変更をトリガーするにはどうすればよいですか?

私のJSの知識は非常に限られていますが、素敵で簡単な解決策があるかもしれませんthx

21
lauWM

私はこれを行う素敵な方法を探していましたが、マーカーにIDを与えるための組み込みの方法(リーフレットを使用する)はまだないことがわかります。 私はこれに答えるのに少し遅れていることを知っていますが、うまくいけば、この質問につまずく人を助けるでしょう。私が知る限り、ここには2つの主要な問題があります。

問題#1:以下で説明するオブジェクトまたはマップにマーカーを保存しない限り、後でそれらにアクセスする簡単なプログラム方法はありません。たとえば、ユーザーがマップ内のマーカーに対応するマップ外の何かをクリックします。

問題#2:ユーザーがマップ内のマーカーをクリックすると、そのマーカーのIDを取得して使用する組み込みの方法はありません対応する要素を強調表示するか、マップ外でアクションをトリガーします。

解決策

これらのオプションを1つ以上使用すると、上記の問題に対処できます。前の回答で言及したものから始めます。以下に working pen を示します。これには以下にあるすべてのコードが含まれています。

オプション#1:オブジェクト内にハードコードされたIDまたは動的IDを使用して各マーカーを保存します-

// Create or retrieve the data
var data = [
    {
      name: 'Bob',
      latLng: [41.028, 28.975],
      id: '2342fc7'
    }, {...}, {...}
];

// Add an object to save markers
var markers = {};

// Loop through the data
for (var i = 0; i < data.length; i++) {
  var person = data[i];

  // Create and save a reference to each marker
  markers[person.id] = L.marker(person.latLng, {
    ...
  }).addTo(map);
}

他の回答と同様に、次を使用して単一のマーカーにアクセスできるようになりました-

var marker = markers.2342fc7; // or markers['2342fc7']

オプション#2:

リーフレットはマーカーの組み込みの 'id'オプションを提供しませんが、._iconプロパティにアクセスして、要素にIDを直接追加できます。

// Create and save a reference to each marker
markers[person.id] = L.marker(person.latLng, {...}).addTo(map);

// Add the ID
markers[person.id]._icon.id = person.id;

これで、クリックイベントを処理するときに、マーカーのIDを簡単に取得できます。

$('.leaflet-marker-icon').on('click', function(e) {
   // Use the event to find the clicked element
   var el = $(e.srcElement || e.target),
       id = el.attr('id');

    alert('Here is the markers ID: ' + id + '. Use it as you wish.')
});

オプション#3:

別のアプローチは、layerGroupインターフェイスを使用することです。 IDを使用してマーカーを取得するのに最適だと思われるgetLayerメソッドを提供します。ただし、現時点では、リーフレットはカスタムIDまたは名前を指定する方法を提供していません。 Githubのこの issue では、これを行う方法について説明しています。ただし、次のように、マーカーの自動生成ID(またはその場合はiLayer)を取得して保存できます。

var group = L.layerGroup()

people.forEach(person => {
    // ... create marker
    group.addLayer( marker );
    person.marker_id = group.getLayerId(marker)
})

データの配列内の各バッキングオブジェクトとともにすべてのマーカーのIDが保存されたので、後ほど簡単にマーカーを取得できます。

group.getLayer(person.marker_id)

完全な例については、 this pen を参照してください...

オプション#4:

これを行う最もクリーンな方法は、時間があれば、リーフレットのマーカークラスを拡張して、個々のニーズをきれいに処理することです。オプションにIDを追加するか、ID /クラスを持つマーカーにカスタムHTMLを挿入できます。詳細については documentation をご覧ください。

circleMarker を使用することもできます。これは path options で、同様のマーカーのグループをスタイリングするのに適したclassNameのオプションがあります。

スタイリング:

あなたの元の質問がスタイリングの目的で提示されたことをほとんど忘れていました...単にIDを使用して個々の要素にアクセスします:

.leaflet-marker-icon#2342fc7 { ... }

結論

また、レイヤーとフィーチャグループは、マーカーとのインターフェイスに別の優れた方法を提供することにも触れます。これを少し説明する question があります。 最初の または 2番目のペン をいじったり、フォークしたりして、何か見逃した場合はコメントしてください。

37
Skip Jack

これを行う簡単な方法は、一意のIDを持つすべてのマーカーをリストに追加することです。

var markersObject = {};
markersObject["id1"] = marker1;
markersObject["id2"] = marker2;
markersObject["id3"] = marker3;

レストランのリストに、追加されたマーカーのIDに対応する単一のレストランのhtml要素にプロパティがある場合。何かのようなもの:

<a href="#" id="singleRestaurantItem" data-restaurantID="id1" data-foo="bar">Click</a>

次に、レストランのID(この場合は「data-restaurantID」)を渡すクリックイベントを追加し、次のようにします。

markersObject["passedValueFromTheClickedElement"].openPopup();

この方法では、リスト内のアイテムをクリックすると、マーカーのポップアップが開き、地図上のどこにレストランがあるかを示します。

6
Marko Letic
var MarkerIcon = L.Icon.extend({
    options: {
        customId: "",
        shadowUrl: 'leaf-shadow.png',
        iconSize: [64, 64],
        shadowSize: [50, 64],
        iconAnchor: [22, 94],
        shadowAnchor: [4, 62],
        popupAnchor: [-3, -76]
    }
});

var greenIcon = new MarkerIcon({iconUrl: "/resources/images/marker-green.png"}),            
    redIcon = new MarkerIcon({iconUrl: "/resources/images/marker-red.png"}),
    orangeIcon = new MarkerIcon({iconUrl: "/resources/images/marker-orange.png"});

var mymap = L.map('mapid').setView([55.7522200, 37.6155600], 13);

L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
    maxZoom: 18,
    id: 'mapbox.streets'
}).addTo(mymap);

// добавить маркер
L.marker([55.7522200, 37.6155600], {customId:"010000006148", icon: greenIcon, title:setMarkerTitle("010000006148")}).addTo(mymap).on('click', markerOnClick);
L.marker([55.7622200, 37.6155600], {customId:"010053166625", icon: redIcon, title: setMarkerTitle("010053166625")}).addTo(mymap).on('click', markerOnClick);

function markerOnClick(e) {
    var customId = this.options.customId;
    document.location.href = "/view/abonents/" + customId;
}

function setMarkerTitle(customId){
    var result = customId;
    result += "\nline2 ";
    result += "\nline3 ";
    return result;
}
4
Slava84

私の場合、最善の方法は、作成時に_L.marker_のOptionsオブジェクトに一意のIDを生成して渡すことです。

_const newMarker = L.marker([lat, lng], {uniqueID: uniqueID})
_

その後、このマーカーをリーフレットlayerGroupに追加できます。

_const newLayerGroup = L.layerGroup().addTo(map);
newLayerGroup.addLayer(newMarker);
_

_layer.options.uniqueID_を使用してIDにアクセスできます。これにより、後でマーカーを検索して操作できます。必要なのは、リーフレットの.eachLayer()とuniqueIDだけです。

私のバックエンド(Cloud Firestore)は既に一意のドキュメントIDを生成しているため、layerGroup全体を再構築して再マウントしたり、ページを更新したりするのではなく、リーフレットマップとバックエンドをリアルタイムで非常に簡単に同期できます。

_//e.g. a callback which fires whenever a doc has been removed from my db

newLayerGroup.eachLayer((layer) => {
  if (deletedDocID === layer.options.uniqueID) {
    newLayerGroup.removeLayer(layer);
  }
});
_
1
Brendan McGill