Reputation: 1491
Please consider the following code http://jsfiddle.net/franckl/311bcbc8/
var southWest = L.latLng(-90, -180),
northEast = L.latLng(90, 180);
var bounds = L.latLngBounds(southWest, northEast);
var map = L.map('map', {
minZoom: 2,
zoomControl: false,
attributionControl: false,
maxBounds: bounds
});
// Using cartoDB basemap
L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
minZoom: 2,
subdomains: 'abcd',
detectRetina: true,
attribution: ''
}).addTo(map);
map.fitBounds(bounds);
var newMarker0 = L.marker(map.getCenter(), {
icon: new L.Icon.Default(),
zIndexOffset: 10000,
draggable: true
});
newMarker0.addTo(map);
html
<div id="mycontainer">
<div id="map"></div>
</div>
css
body {
margin:0;
padding:0;
}
#map {
position:absolute;
top:0;
bottom:0;
width:300px;
}
#mycontainer {
top: 10px;
width: 600px;
height: 250px;
position: relative;
}
If you drag the marker to the right, it leaves visible area of the map. How can I prevent the user from dragging the marker outside the map ?
Thanks !
Upvotes: 2
Views: 2803
Reputation: 26253
A solution with slightly more generic code and tailored to dragging the marker rather than the map, but derivative of @Franckl's:
onMarkerDrag: function (event) {
// keep dragged marker within map bounds
var containerPoint = this.map.latLngToContainerPoint(event.target.getLatLng()),
clampX = null,
clampY = null,
MARKER_MARGIN = 10;
if (containerPoint.x - MARKER_MARGIN < 0) {
clampX = MARKER_MARGIN;
} else if (containerPoint.x + MARKER_MARGIN > this.mapContainerBounds.width) {
clampX = this.mapContainerBounds.width - MARKER_MARGIN;
}
if (containerPoint.y - MARKER_MARGIN < 0) {
clampY = MARKER_MARGIN;
} else if (containerPoint.y + MARKER_MARGIN > this.mapContainerBounds.height) {
clampY = this.mapContainerBounds.height - MARKER_MARGIN;
}
if (clampX !== null || clampY !== null) {
if (clampX !== null) { containerPoint.x = clampX; }
if (clampY !== null) { containerPoint.y = clampY; }
marker.setLatLng(this.map.containerPointToLatLng(containerPoint));
}
},
I derive this.mapContainerBounds
once on map init instead of every time the drag handler fires (my map does not change size), like this:
this.mapContainerBounds = mapDOMNode.getBoundingClientRect();
Upvotes: 0
Reputation: 1491
answering my own question in case it helps anyone. We detect the map container size and check if the marker is going outside the visible area by converting its lat/lng coordinates to a container point (map.containerPointToLatLng(markerContainerPosition))
As a bonus, this code leaves the marker in the same position relative to the map container when the user moves the map. It ensures that the marker never goes outside the visible area (even when zooming)
var southWest = L.latLng(-90, -180),
northEast = L.latLng(90, 180);
var bounds = L.latLngBounds(southWest, northEast);
var map = L.map('map', {
minZoom: 2,
zoomControl: false,
attributionControl: false,
maxBounds: bounds
});
// Using cartoDB basemap
L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
minZoom: 2,
subdomains: 'abcd',
detectRetina: true,
attribution: ''
}).addTo(map);
map.fitBounds(bounds);
var newMarker0 = L.marker(map.getCenter(), {
icon: new L.Icon.Default(),
zIndexOffset: 10000,
draggable: true
});
newMarker0.addTo(map);
var mapSize = map.getSize();
var markerContainerPosition = map.latLngToContainerPoint(newMarker0.getLatLng());
function mapMove() {
newMarker0.setLatLng(map.containerPointToLatLng(markerContainerPosition));
}
function markerDrag(e) {
var mTempContainerPos = map.latLngToContainerPoint(newMarker0.getLatLng());
var newPos;
if (mTempContainerPos.x < 20) {
if (mTempContainerPos.y < 45) {
newPos = L.point(20, 45);
} else if (mTempContainerPos.y > (mapSize.y - 20)) {
newPos = L.point(20, mapSize.y - 20);
} else {
newPos = L.point(20, mTempContainerPos.y);
}
} else if (mTempContainerPos.x > mapSize.x - 20) {
if (mTempContainerPos.y < 45) {
newPos = L.point(mapSize.x - 20, 45);
} else if (mTempContainerPos.y > (mapSize.y - 20)) {
newPos = L.point(mapSize.x - 20, mapSize.y - 20);
} else {
newPos = L.point(mapSize.x - 20, mTempContainerPos.y);
}
} else {
if (mTempContainerPos.y < 45) {
newPos = L.point(mTempContainerPos.x, 45);
} else if (mTempContainerPos.y > (mapSize.y - 20)) {
newPos = L.point(mTempContainerPos.x, mapSize.y - 20);
}
}
if (newPos) {
markerContainerPosition = newPos;
newMarker0.setLatLng(map.containerPointToLatLng(newPos));
} else {
markerContainerPosition = mTempContainerPos;
}
}
map.on('move', mapMove);
newMarker0.on('drag', markerDrag);
Upvotes: 3