简单 Leaflet.js 标记放置

Simple Leaflet.js Marker Placement

我正在使用 open source Leaflet.js library 创建一个简单的地图。

不过我正在尝试解决一个具体问题。标记绑定到地图上的特定 lat/lng,这是有道理的,但我需要能够使标记与另一个标记具有固定的偏移位置,而不绑定到 lat/lng 中心.

例如,地图可能如下所示:

但是当你缩小时,它看起来像这样:


我真正想要的是右标记与左标记有一个固定的偏移量,而不是像这样绑定到 latlng:


我尝试过 unproject 但我相信我在处理这个问题上走错了路。我正在做的事情是非常规的,但如果有人对我如何做到这一点有任何见解,我将不胜感激。

除了 project()unproject() 计算第二个标记位置的方法之外,您还可以监听地图上的缩放事件并更新第二个标记的位置,以保持所需的位置以像素为单位的距离。

看看下面的例子。

var marker;
var pos = L.latLng(28.478226,-16.313488);
var mymap = L.map('mapid').setView(pos, 13);
 
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
  maxZoom: 18,
  attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
   '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
   'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
  id: 'mapbox.streets'
}).addTo(mymap);

L.marker(pos).addTo(mymap);
  
setLinkedMarkerAtDistance(180);
  
mymap.on('zoomstart', function() {
  if (marker) {
   mymap.removeLayer(marker);
  }
});
  
mymap.on('zoomend', function() {
  setLinkedMarkerAtDistance(180);
});

function setLinkedMarkerAtDistance(d) {
  var p = mymap.project(pos, mymap.getZoom());
  var p1 = p.add(L.point(d,0));
  var pos1 = mymap.unproject(p1, mymap.getZoom());
  if (marker) {
    marker.setLatLng(pos1).addTo(mymap);
  } else {
   marker = L.marker(pos1).addTo(mymap);
  }
}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.3.4/dist/leaflet.js" integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA==" crossorigin=""></script>
<div id="mapid" style="width: 600px; height: 400px;">

希望对您有所帮助!

这对我来说听起来像是 XY problem:您想在标记 A(有一些像素偏移)旁边显示一些额外的信息(可能看起来类似于普通标记),然后尝试使用另一个标记B;但是标记 B 绑定到 Lat/Lng 坐标而不是像素偏移,因此您寻求有关如何使用 unproject.

的帮助

要实现您原来的 objective,传单 DivIcon would 是更合适的解决方案:<div> 的一部分将包含您的实际标记图标,另一部分将包含你的额外信息。这样,它始终停留在所需位置,无需计算任何(非)投影,也无需涉及任何 JS 事件侦听器:

var paris = [48.86, 2.35];
var map = L.map('map').setView(paris, 11);

var divIcon = L.divIcon({
  html: `
    <img src="https://unpkg.com/leaflet@1.3.4/dist/images/marker-icon.png" />
    <div class="extra-info">
      Some extra info
    </div>
  `,
  className: 'my-div-icon',
  iconAnchor: [12, 41]
});

L.marker(paris, {
  icon: divIcon
}).addTo(map);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
html,
body,
#map {
  height: 100%;
  margin: 0;
}

.extra-info {
  position: absolute;
  left: 188px;
  bottom: -20px;
  min-width: 120px;
  background: yellow;
  border: 1px solid red;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.3.4/dist/leaflet-src.js" integrity="sha512-+ZaXMZ7sjFMiCigvm8WjllFy6g3aou3+GZngAtugLzrmPFKFK7yjSri0XnElvCTu/PrifAYQuxZTybAEkA8VOA==" crossorigin=""></script>

<div id="map"></div>

一个更合适的解决方案是使用 Leaflet Tooltip, typically with your predefined offset, permanent: true option, a specific direction 和自定义样式(使用 className):

var paris = [48.86, 2.35];
var map = L.map('map').setView(paris, 11);

L.marker(paris).bindTooltip('Some extra info', {
  offset: [188, 0],
  className: 'my-tooltip',
  permanent: true,
  direction: 'right',
  interactive: true
}).addTo(map);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
html,
body,
#map {
  height: 100%;
  margin: 0;
}

.leaflet-tooltip.my-tooltip {
  background-color: yellow;
  border: 1px solid red;
  box-shadow: none;
}

.leaflet-tooltip.my-tooltip::before {
  content: none;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.3.4/dist/leaflet-src.js" integrity="sha512-+ZaXMZ7sjFMiCigvm8WjllFy6g3aou3+GZngAtugLzrmPFKFK7yjSri0XnElvCTu/PrifAYQuxZTybAEkA8VOA==" crossorigin=""></script>

<div id="map"></div>

那么如果你真的希望你的额外信息像普通的传单标记一样被设计和操作,另一种可能的解决方案是使用修改后的自定义标记 iconAnchor, 以说明您想要的像素偏移量:

var paris = [48.86, 2.35];
var map = L.map('map').setView(paris, 11);

var OffsetIcon = L.Icon.Default.extend({
  options: {
    // Subtract your desired offset.
    iconAnchor: [12 - 188, 41]
  }
});

L.marker(paris).addTo(map);
L.marker(paris, {
  icon: new OffsetIcon()
}).addTo(map);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
html,
body,
#map {
  height: 100%;
  margin: 0;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.3.4/dist/leaflet-src.js" integrity="sha512-+ZaXMZ7sjFMiCigvm8WjllFy6g3aou3+GZngAtugLzrmPFKFK7yjSri0XnElvCTu/PrifAYQuxZTybAEkA8VOA==" crossorigin=""></script>

<div id="map"></div>