传单:防止标记被拖到地图容器之外
leaflet : Prevent marker to be dragged outside the map container
请考虑以下代码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;
}
如果向右拖动标记,它会离开地图的可见区域。
如何防止用户将标记拖到地图外?
谢谢!
回答我自己的问题以防对任何人有帮助。
我们检测地图容器大小,并通过将其 lat/lng 坐标转换为容器点 (map.containerPointToLatLng(markerContainerPosition))
来检查标记是否超出可见区域
作为奖励,此代码在用户移动地图时将标记留在相对于地图容器的相同位置。它确保标记永远不会超出可见区域(即使在缩放时)
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);
一个代码稍微更通用的解决方案,适合拖动标记而不是地图,但是 @Franckl 的派生:
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));
}
},
我在地图初始化时导出 this.mapContainerBounds
一次,而不是每次触发拖动处理程序时(我的地图不会改变大小),如下所示:
this.mapContainerBounds = mapDOMNode.getBoundingClientRect();
请考虑以下代码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;
}
如果向右拖动标记,它会离开地图的可见区域。 如何防止用户将标记拖到地图外?
谢谢!
回答我自己的问题以防对任何人有帮助。 我们检测地图容器大小,并通过将其 lat/lng 坐标转换为容器点 (map.containerPointToLatLng(markerContainerPosition))
来检查标记是否超出可见区域作为奖励,此代码在用户移动地图时将标记留在相对于地图容器的相同位置。它确保标记永远不会超出可见区域(即使在缩放时)
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);
一个代码稍微更通用的解决方案,适合拖动标记而不是地图,但是 @Franckl 的派生:
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));
}
},
我在地图初始化时导出 this.mapContainerBounds
一次,而不是每次触发拖动处理程序时(我的地图不会改变大小),如下所示:
this.mapContainerBounds = mapDOMNode.getBoundingClientRect();