传单检测标记何时进入和离开圆圈

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 &copy; <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 &copy; <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 的回答。