简体   繁体   中英

Simple Leaflet.js Marker Placement

I'm using the open source Leaflet.js library to create a simple map.

I'm trying to solve a specific problem though. Markers are tied to a specific lat/lng on a map, which makes sense, but I need to be able to make a marker have a fixed offset position from another marker, without it being tied to a lat/lng center.

So for example, the map may look like this: 两个标记的leaflet.js映射

But when you zoom out, it'll look like this: 在此处输入图片说明


What I actually want is for the right marker to be a fixed offset away from the left marker, instead of being tied to a latlng, as such: 在此处输入图片说明


I've tried experimenting with unproject but I believe I'm going down the wrong path of how to handle this. It's unconventional what I'm doing but if anyone has any insight into how I could do this, it would be greatly appreciated.

In addition to project() and unproject() methods to calculate position of second marker you can also listen to zoom events on the map and update the position of the second marker in order to keep the desired distance in pixels.

Have a look at the following example.

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

I hope this helps!

This sounds like an XY problem to me: you want to display some extra info (possibly looking similar to a normal Marker) next to a Marker A (with some pixels offset), and you try with another Marker B; but Marker B is tied to Lat/Lng coordinates instead of pixels offset, so you ask for help on how to use unproject .

To achieve your original objective, a Leaflet DivIcon would indeed have been a more appropriate solution: a part of the <div> would contain your actual Marker Icon, and another part would contain your extra info. That way, it always stays at the desired position, without having to compute any (un)projection and without any JS event listener involved:

屏幕快照地图在DivIcon中带有Marker,带有额外的信息框

 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> 

An even more appropriate solution would have been to use a Leaflet Tooltip , typically with your predefined offset , permanent: true option, a specific direction and custom styling (with 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> 

Then if you really want your extra info to be styled and manipulated like a normal Leaflet Marker, another possible solution would be to use a custom Marker with modified iconAnchor , to account for your desired pixel offset:

 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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM