将标识分配给传单中的标记

时间:2014-09-05 10:32:27

标签: javascript html css maps leaflet

所以我试着在foursquare上实现一个结果:https://foursquare.com/explore?cat=drinks&mode=url&near=Paris当你在地图上标记时,它会滚动浏览屏幕右侧的餐馆列表到广告特约餐厅,并通过CSS突出显示它。相反,当您点击列表中的餐厅时,它会在地图上突出显示它。

我正在使用skobbler / leaflet。我想我可以通过动态修改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();

问题是:如何在html页面中的相应元素中指定标记ID来触发css更改?

我对JS的了解非常有限,但可能会有一个很好的解决方案,那就是

7 个答案:

答案 0 :(得分:33)

我一直在寻找一种很好的方法来做到这一点,据我所知,仍然没有内置方式(使用传单)给标记一个ID。 我知道我回答这个问题有点迟,但希望它会帮助那些偶然发现这个问题的人。据我所知,这里有两个主要问题:

问题#1: 除非您将标记保存到对象或地图(如下所述),否则以后无法轻松以编程方式访问它们。例如 - 用户点击地图外的东西,该地图对应于地图内的标记。

问题#2: 当用户单击地图内的标记时,没有内置方法来检索该标记的ID,然后使用它来突出显示相应的元素或触发地图外的操作。

解决方案

使用这些选项中的一个或多个将有助于解决上述问题。我将从上一个答案中提到的那个开始。这是working pen,其中包含下面的所有代码。

选项#1: 在对象内使用硬编码或动态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接口。它提供了一种方法,getLayer,听起来像是完美的使用ID获取我们的标记。但是,目前,Leaflet 未提供任何指定自定义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,也可以将自定义HTML插入到具有您的id / class的标记中。有关详细信息,请参阅documentation

您还可以使用circleMarker,在path options中,您会看到有一个className选项,可以很好地为类似标记的样式组设置样式。

<强>样式:

几乎忘记了您的原始问题是为了造型而提出的......只需使用ID来访问各个元素:

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

结论

我还要提到图层和要素组提供了另一种与标记交互的好方法。这是一个question,讨论了这一点。如果我错过了某些内容,请随意修改或分叉firstsecond pen并发表评论。

答案 1 :(得分:6)

一种简单的方法是将所有标记添加到具有唯一ID的列表中。

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

如果餐馆列表在单个餐馆的html元素中具有与添加的标记的id相对应的属性。类似的东西:

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

然后添加点击事件,您将在其中传递餐厅的ID(在本例中为&#34; data-restaurantID&#34;)并执行以下操作:

markersObject["passedValueFromTheClickedElement"].openPopup();

这样一旦你点击列表中的项目,就会打开一个标记弹出窗口,指示地图上餐馆的位置。

答案 2 :(得分:3)

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

答案 3 :(得分:0)

对于我的情况,我发现最好的方法是在创建时简单地生成并传递唯一ID到L.marker的Options对象。

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

然后,您可以将此标记添加到传单layerGroup

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

您可以使用layer.options.uniqueID访问ID。这样我就可以在以后找到并操作标记;我需要的只是Leaflet的.eachLayer()和uniqueID。

我的后端(Cloud Firestore)已经生成了唯一的文档ID,这使得我可以非常轻松地实时同步我的Leaflet地图和后端,而不是重建和重新安装整个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);
  }
});

答案 4 :(得分: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();
    });
  }

答案 5 :(得分:0)

1。)让我们创建具有唯一ID的标记...

L.marker([marker.lat, marker.lng],{customID:'some ID',title:marker.title}).on('click', this.markerClick).addTo(mymap);

2。)转到node_modules @ types \ leaflet \ index.d.ts并添加customID?:string;

export interface MarkerOptions extends InteractiveLayerOptions {
    icon?: Icon | DivIcon;
    title?: string;

    ....

    autoPanSpeed?: number;
    customID:string;
}

3。)在同一文件中,将customID添加到LeafletMouseEvent

export interface LeafletMouseEvent extends LeafletEvent {
  latlng: LatLng;
  layerPoint: Point;
  containerPoint: Point;
  originalEvent: MouseEvent;
  customID:customID
}

4。)创建customID类

export class customID {
  constructor(customID: string);
  customID: number;
} 

5。)在功能中获取您的标记ID

markerClick(e){
  console.log(e.sourceTarget.options.customID)
}

答案 6 :(得分:-1)

Leaflet className option可以允许一个人向对象添加标识符:

var onMouseover = function() {
  // returns all members of the specified class
  d3.selectAll(".mySpecialClass")
    .style("opacity", ".1");
};

// add desired class to pointer 
L.circleMarker([46.85, 2.35], {className: "mySpecialClass"})
  .addTo(map).on('mouseover', onMouseover);

// to select the marker(s) with a particular class, just use css selectors
// here's a d3.js solution
d3.selectAll(".mySpecialClass")
  .style("opacity", ".3")