传单检测标记何时进入和离开圆圈
Leaflet detect when marker goes into and out of a circle
我正在尝试使用传单进行地理围栏,我有一个可以移动的标记和地图上的一个圆圈。
完整代码如下:
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<head>
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-locatecontrol/v0.43.0/css/font-awesome.min.css' rel='stylesheet' />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
</head>
<body>
<div id="mapid" style="height: 600px"></div>
<script>
var mymap = L.map('mapid', {
center: [50.897819, -1.150189],
zoom: 16
});
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic3RldmVuc2F0Y2giLCJhIjoiY2p5eDR6MWgzMHRvbjNocnJkN2d2MjRwaSJ9.wd0OtBUQQfUtNxdduQA3lg', {
maxZoom: 18,
attribution: 'Map data © <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);
var marker = new L.marker([50.898422, -1.148444],{
draggable: true,
autoPan: true
}).addTo(mymap);
var circle = L.circle([50.895763, -1.150556], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 200
}).addTo(mymap);
</script>
</body>
</body>
</html>
我需要检测标记何时进入和离开圆圈。
我该怎么做?
- 拖动标记时可以听drag event动作
- 然后您可以确定标记是否在您的圆圈内,例如通过计算到圆心的距离。
类似于
marker.on('drag', function(e) {
// distance between the current position of the marker and the center of the circle
var d = mymap.distance(e.latlng, circle.getLatLng());
// the marker is inside the circle when the distance is inferior to the radius
var isInside = d < circle.getRadius();
// let's manifest this by toggling the color
circle.setStyle({
fillColor: isInside ? 'green' : '#f03'
})
});
还有一个演示
var mymap = L.map('mapid', {
center: [50.895763, -1.150556],
zoom: 16
});
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic3RldmVuc2F0Y2giLCJhIjoiY2p5eDR6MWgzMHRvbjNocnJkN2d2MjRwaSJ9.wd0OtBUQQfUtNxdduQA3lg', {
maxZoom: 18,
attribution: 'Map data © <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);
var marker = new L.marker([50.896422, -1.148444],{
draggable: true,
autoPan: true
}).addTo(mymap);
var circle = L.circle([50.895763, -1.150556], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 100
}).addTo(mymap);
marker.on('drag', function(e) {
var d = mymap.distance(e.latlng, circle.getLatLng());
var isInside = d < circle.getRadius();
circle.setStyle({
fillColor: isInside ? 'green' : '#f03'
})
});
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-locatecontrol/v0.43.0/css/font-awesome.min.css' rel='stylesheet' />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@5/turf.min.js"></script>
<div id="mapid" style="height: 180px"></div>
另一种方法是检查圆圈是否在标记被拖动到的像素处呈现;这可以通过利用 Leaflet.CheapLayerAt plugin 来完成,例如:
<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.cheaplayerat@0.1.2/Leaflet.CheapLayerAt.js"></script>
和
marker.on('dragend', function(ev) {
// Hide the marker momentarily, so CheapLayerAt doesn't return it
marker.getElement().style.display = 'none';
if (map.getLayerAtLatLng(marker.getLatLng()) === circle) {
// The marker was dragged inside
} else {
// The marker was dragged outside
}
// Display the marker icon again
marker.getElement().style.display = 'inherit';
});
这种方法有一些缺点 - 在 拖动过程中很难使用 id ,因为隐藏标记然后在拖动操作中再次显示它可能会触发更多 DOM 事件和乱七八糟的事情。如果标记看起来像默认标记,则可以改为计算像素 正下方 标记尖端下方的图层,例如:
marker.on('drag', function(ev) {
var pxPos = map.latLngToContainerPoint(marker.getLatLng());
pxPos.y += 1;
if (map.getLayerAt(pxPos) === circle) {
// The marker was dragged inside
} else {
// The marker was dragged outside
}
});
请记住,当标记被拖到圆的边界上时,这种方法会告诉您。如果圆的 stroke weight 太宽,即使标记到圆心的距离大于圆半径,也会在标记刚好超过边界时得到结果。
因此,尽管这回答了您的问题 ("When is the marker dragged over the circle?"),但我认为您问错了问题。对于地理围栏,您想知道一个点是否在给定距离内到另一个已知点,所以我会接受@nikoshr 的回答。
我正在尝试使用传单进行地理围栏,我有一个可以移动的标记和地图上的一个圆圈。
完整代码如下:
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<head>
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-locatecontrol/v0.43.0/css/font-awesome.min.css' rel='stylesheet' />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
</head>
<body>
<div id="mapid" style="height: 600px"></div>
<script>
var mymap = L.map('mapid', {
center: [50.897819, -1.150189],
zoom: 16
});
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic3RldmVuc2F0Y2giLCJhIjoiY2p5eDR6MWgzMHRvbjNocnJkN2d2MjRwaSJ9.wd0OtBUQQfUtNxdduQA3lg', {
maxZoom: 18,
attribution: 'Map data © <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);
var marker = new L.marker([50.898422, -1.148444],{
draggable: true,
autoPan: true
}).addTo(mymap);
var circle = L.circle([50.895763, -1.150556], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 200
}).addTo(mymap);
</script>
</body>
</body>
</html>
我需要检测标记何时进入和离开圆圈。
我该怎么做?
- 拖动标记时可以听drag event动作
- 然后您可以确定标记是否在您的圆圈内,例如通过计算到圆心的距离。
类似于
marker.on('drag', function(e) {
// distance between the current position of the marker and the center of the circle
var d = mymap.distance(e.latlng, circle.getLatLng());
// the marker is inside the circle when the distance is inferior to the radius
var isInside = d < circle.getRadius();
// let's manifest this by toggling the color
circle.setStyle({
fillColor: isInside ? 'green' : '#f03'
})
});
还有一个演示
var mymap = L.map('mapid', {
center: [50.895763, -1.150556],
zoom: 16
});
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic3RldmVuc2F0Y2giLCJhIjoiY2p5eDR6MWgzMHRvbjNocnJkN2d2MjRwaSJ9.wd0OtBUQQfUtNxdduQA3lg', {
maxZoom: 18,
attribution: 'Map data © <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);
var marker = new L.marker([50.896422, -1.148444],{
draggable: true,
autoPan: true
}).addTo(mymap);
var circle = L.circle([50.895763, -1.150556], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 100
}).addTo(mymap);
marker.on('drag', function(e) {
var d = mymap.distance(e.latlng, circle.getLatLng());
var isInside = d < circle.getRadius();
circle.setStyle({
fillColor: isInside ? 'green' : '#f03'
})
});
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-locatecontrol/v0.43.0/css/font-awesome.min.css' rel='stylesheet' />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@5/turf.min.js"></script>
<div id="mapid" style="height: 180px"></div>
另一种方法是检查圆圈是否在标记被拖动到的像素处呈现;这可以通过利用 Leaflet.CheapLayerAt plugin 来完成,例如:
<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.cheaplayerat@0.1.2/Leaflet.CheapLayerAt.js"></script>
和
marker.on('dragend', function(ev) {
// Hide the marker momentarily, so CheapLayerAt doesn't return it
marker.getElement().style.display = 'none';
if (map.getLayerAtLatLng(marker.getLatLng()) === circle) {
// The marker was dragged inside
} else {
// The marker was dragged outside
}
// Display the marker icon again
marker.getElement().style.display = 'inherit';
});
这种方法有一些缺点 - 在 拖动过程中很难使用 id ,因为隐藏标记然后在拖动操作中再次显示它可能会触发更多 DOM 事件和乱七八糟的事情。如果标记看起来像默认标记,则可以改为计算像素 正下方 标记尖端下方的图层,例如:
marker.on('drag', function(ev) {
var pxPos = map.latLngToContainerPoint(marker.getLatLng());
pxPos.y += 1;
if (map.getLayerAt(pxPos) === circle) {
// The marker was dragged inside
} else {
// The marker was dragged outside
}
});
请记住,当标记被拖到圆的边界上时,这种方法会告诉您。如果圆的 stroke weight 太宽,即使标记到圆心的距离大于圆半径,也会在标记刚好超过边界时得到结果。
因此,尽管这回答了您的问题 ("When is the marker dragged over the circle?"),但我认为您问错了问题。对于地理围栏,您想知道一个点是否在给定距离内到另一个已知点,所以我会接受@nikoshr 的回答。