13

I have setup a draggable marker on my map with Leaflet API. Its working fine. But the problem is when I am trying to drag it to the border area the map is not moving. I want a panning map with Marker dragging. Please let me also know how can able to control the map panning when dragging the marker.

Thanks

DPSSpatial_BoycottingGISSE
  • 18,790
  • 4
  • 66
  • 110
Devils Dream
  • 3,179
  • 9
  • 44
  • 78

4 Answers4

18

you can use map.panTo():

function onMapClick(e) {
  marker = new L.marker(e.latlng, {draggable:'true'});
  marker.on('dragend', function(event){
    var marker = event.target;
    var position = marker.getLatLng();
    marker.setLatLng(new L.LatLng(position.lat, position.lng),{draggable:'true'});
    map.panTo(new L.LatLng(position.lat, position.lng))
  });
  map.addLayer(marker);
};

map.on('click', onMapClick);

Complete html with inline js (minus cloudmade api):

<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.css" />
<!--[if lte IE 8]>
 <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.ie.css" />
<![endif]-->
<script src="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>

<div id="map" style="width: 600px; height: 600px;"></div>

<script>

var map = L.map('map').setView([51.505, -0.09], 13);

L.tileLayer('http://{s}.tile.cloudmade.com/API-KEY/997/256/{z}/{x}/{y}.png', {
  attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery ©     <a href="http://cloudmade.com">CloudMade</a>',
  maxZoom: 18
}).addTo(map);

function onMapClick(e) {
  marker = new L.marker(e.latlng, {draggable:'true'});
  marker.on('dragend', function(event){
    var marker = event.target;
    var position = marker.getLatLng();
    marker.setLatLng(new L.LatLng(position.lat, position.lng),{draggable:'true'});
    map.panTo(new L.LatLng(position.lat, position.lng))
  });
  map.addLayer(marker);
};

map.on('click', onMapClick);

</script>
toms
  • 6,978
  • 1
  • 25
  • 30
  • Thanks for your answer. But probably you didn't get my point. In your solution when the marker is released at that time map is panning. But I need something like at the time of grabbing the marker I can pan left right or up down. In simple word I want a real-time pan when grab the draggable marker. – Devils Dream Dec 13 '13 at 13:33
10

Leaflet now provides this as an option with creating a marker, so there is no need to attach a drag event to pan the map.

Link to docs: https://leafletjs.com/reference-1.3.4.html#marker-autopan

Code sample:

var marker = new L.marker([lat,lon],{
    draggable: true,
    autoPan: true
}).addTo(map);
John Powell
  • 13,649
  • 5
  • 46
  • 62
shazahm1
  • 101
  • 1
  • 2
7

In case someone else stumbles upon this and needs a live pan, too.

Just remove the click event like so:

var marker = new L.marker([lat,lon],{
    draggable: true
}).addTo(map);

marker.on("drag", function(e) {
    var marker = e.target;
    var position = marker.getLatLng();
    map.panTo(new L.LatLng(position.lat, position.lng));
});

I wished it would be even more real time, it lags a little behind the mouse.

Can Rau
  • 171
  • 1
  • 3
1

A little different approach here. This will pan the map to where the mouse position is every 1 second. It is pretty smooth though.

This is typescript:

        var mapContainer = $(".detail-bottom-wrap .map-container");
        var mapWidth = -1;
        var mapHeight = -1;
        var mapPosition = null;
        var panPositionThreshold = this.shared.isTablet ? 100 : 60;

        this.draggableMarker.on("drag", (e: any) => {
            var pointerEvents = e.originalEvent.touches;
            if (pointerEvents.length != 1)
                return;

            //Only set on first time drag happens
            if (mapWidth == -1) {
                mapPosition = mapContainer.offset();
                mapWidth = mapContainer.width();
                mapHeight = mapContainer.height();
            }

            //Check left and right boundaries
            this.panningMapEvent = e.originalEvent;
            var mouseX = e.originalEvent.x
            var mouseY = e.originalEvent.y;

            if (mouseX < mapPosition.left + panPositionThreshold) {
                //Dragging to left
                this.togglePanningMode(true);
            }
            else if (mouseX > mapPosition.left + mapWidth - panPositionThreshold) {
                //Dragging to right
                this.togglePanningMode(true);
            }
            else {
                this.togglePanningMode(false);
            }

        });
        this.draggableMarker.on("dragend", (e: any) => {
            mapWidth = -1;
            this.togglePanningMode(false);
        });

 private togglePanningMode(active: boolean) {
    this.draggableMarker.setLatLng(this.map.mouseEventToLatLng(this.panningMapEvent));

    if (active) {
        //Only start interval if it's been stopped
        if (this.panningActiveId == -1) {
            window.clearInterval(this.panningActiveId);
            this.panningActiveId = window.setInterval(() => {
                //Convert mouse position to lat lng, and pan marker
                var mousePositionLatLng: L.LatLng = this.map.mouseEventToLatLng(this.panningMapEvent);
                this.map.panTo(mousePositionLatLng, { animate: true });
                this.draggableMarker.setLatLng(mousePositionLatLng);
                this.map.once("moveend zoomend", () => {
                    this.draggableMarker.setLatLng(this.map.mouseEventToLatLng(this.panningMapEvent));
                });
            }, 1000);
        }
    }
    else {
        window.clearInterval(this.panningActiveId);
        this.panningActiveId = -1;
    }
}