Search code examples
javascriptgoogle-mapsleafletopenstreetmapprojection

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: a leaflet.js map of two markers

But when you zoom out, it'll look like this: enter image description here


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: enter image description here


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.


Solution

  • 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!