TransWikia.com

Leafletjs, how to constrain dragging of a marker to a polyline?

Geographic Information Systems Asked by Andre M on March 18, 2021

Is there a way to constrain a marker so that when it is dragged, it moves along a given polyline in Leaflet JS?

In my page I have route that is presented as a Polyline and a Marker. I want to be able to drag the marker along the line to be able to display information about that part of the route.

Looking at the documentation here, it is not clear how I would go about that:

https://leafletjs.com/reference-1.6.0.html#marker

Note, I am using leaflet by means of vue2leaflet, though a solution that works for standard leaflet JS would be okay.

The vue ‘template’:

      <l-map
        class="leaftlet-map"
        :zoom="map.zoom"
        :center="map.center"
        @update:zoom="zoomUpdated"
        @update:center="centerUpdated"
        @update:bounds="boundsUpdated"
      >
        <l-tile-layer :url="map.url" :attribution="map.attribution" />
        <l-marker
          v-if="positionMarker"
          :lat-lng="positionMarker.center"
          draggable
          @move="markerMoved"
        />
        <l-polyline
          v-if="polyline.latlngs && polyline.latlngs.length > 0"
          :lat-lngs="polyline.latlngs"
          :color="polyline.color"
        />
      </l-map>

One Answer

This is a quick hack just to test the concept. Since img element is draggable by itself, L.divIcon is used for draggable marker so that draggable="false" attribute could be set. For keeping marker glued to polyline, polyline method closestLayerPoint is used to locate closest point to mouse position on polyline.

CSS:

html, body {
  height: 100%;
  padding: 0;
  margin: 0;
}
#map {
  width: 100%;
  height: 100%;
}
.leaflet-div-icon {
  border: none;
  background-color: transparent;
}

HTML:

<div id="map"></div>
<div style="display:none;">
  <img id="icon" draggable="false" src="lib/leaflet/1.6/images/marker-icon.png">
</div>

JS:

var osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: 'Map data &copy; OpenStreetMap contributors',
});

var map = L.map('map').addLayer(osm);

var path = L.polyline([[43, 1],[43, 1.5],[43.5, 2],[44, 3],[43.5, 4]], {
    color: 'red',
    opacity: 1.0
}).addTo(map);

map.fitBounds(path.getBounds());

var myIcon = L.divIcon({
  html: document.getElementById('icon'),
  iconSize: [25, 41],
  iconAnchor: [12.5, 41],
});

var myMarker = L.marker([43, 1], {icon: myIcon}).addTo(map);

myMarker.on({
  mousedown: function () {
    map.on('mousemove', function (e) {
      map.dragging.disable();
      var point = path.closestLayerPoint(map.latLngToLayerPoint(e.latlng))
      myMarker.setLatLng(map.layerPointToLatLng(point));
    });
  }
}); 
map.on('mouseup',function(e){
  map.removeEventListener('mousemove');
  map.dragging.enable();
});

Answered by TomazicM on March 18, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP