如何使用Leaflet.draw获取选择的标记? [英] How can I grab a selection of markers with Leaflet.draw?

查看:315
本文介绍了如何使用Leaflet.draw获取选择的标记?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景:

我制作了一张地图,并用大约300个随机标记填充它。我可以通过单击弹出窗口中的链接选择标记,然后激活选择以显示数据。我还有Leaflet.draw插件来绘制圆形,矩形和自定义形状等形状,我想用它来选择几个标记。

I've made a map, and populated it with around 300 random markers. I can 'select' the markers by clicking on a link in the popup and activate a selection to display data from. I also have the Leaflet.draw plugin to draw shapes like circles, rectangles and custom shapes, and I would like to use it to 'select' a couple of markers.

问题

如何抓取落在绘制的leaflet.draw形状内的标记的传单标记对象,以便我可以编辑它们?我似乎无法做出选择,它既不选择任何标记,也不选择所有标记。

How can I grab the leaflet marker object of the markers that fall inside a drawn leaflet.draw shape so I can edit them? I cannot seem to make a selection, It either selects none of the markers, or all of them.

代码片段,从不必要的代码中删除:

Code snippet, stripped from unnecessary code:

const drawControl = new L.Control.Draw({
    draw: {
        marker   : false,
        polygon  : true,
        polyline : false,
        rectangle: true,
        circle   : {
            metric: 'metric'
        }
    },
    edit: false
});

const map = L.map('map', {
    layers: [streets, light]
}).setView([CONFIG.MAP.LATITUDE, CONFIG.MAP.LONGITUDE], CONFIG.MAP.ZOOMLEVEL)

map.addControl(drawControl);

map.on(L.Draw.Event.DRAWSTOP, e => {

    const hello = e.target;

    console.log(hello);
    e.target.eachLayer(layer => {
        if (layer.options.icon) {
            console.log(layer);
        }
    });

});


推荐答案

你想要的大部分内容都可以很容易地完成Leaflet的实用方法。如果你想用复杂的形状做这个,比如 L.Polygon 你需要像 TurfJS

Most of what you want can quite easily be done using Leaflet's utility methods. If you want to do this with a complex shape like L.Polygon you're going to need something like TurfJS

对于 L.Circle ,您需要计算距离圆圈的中心并将其与半径进行比较:

For L.Circle you need to calculate the distance between the circle's center and compare it to the radius:

var marker = new L.Marker(...),
    circle = new L.Circle(...);

var contains = circle.getLatLng().distanceTo(marker.getLatLng()) < circle.getRadius();

对于 L.Rectangle ,您需要提取它是bounds对象并使用contains方法:

For L.Rectangle you need to fetch it's bounds object and use the contains method:

var marker = new L.Marker(...),
    rectangle = new L.Rectangle(...);

var contains = rectangle.getBounds().contains(marker.getLatLng());

如复杂多边形所说,我使用的是Turf但是有更多的库和插件。这是一个使用Turf的里面方法的例子。它需要GeoJSON点和面要素作为参数,因此请注意转换:

As said for complex polygons i'de use Turf but there are more libraries and plugins out there. Here's an example using Turf's inside method. It take a GeoJSON point and polygon feature as parameters so mind the conversion:

var marker = new L.Marker(...),
    polygon = new L.Polygon(...);

var contains = turf.inside(marker.toGeoJSON(), polygon.toGeoJSON());

您可以将这些包装到每个相应类别的便捷方法中:

You could wrap those into convenience methods for each respective class:

L.Polygon.include({
    contains: function (latLng) {
        return turf.inside(new L.Marker(latLng).toGeoJSON(), this.toGeoJSON());
    } 
});

L.Rectangle.include({
    contains: function (latLng) {
        return this.getBounds().contains(latLng);
    }
});

L.Circle.include({
    contains: function (latLng) {
        return this.getLatLng().distanceTo(latLng) < this.getRadius();
    }
});

var marker = new L.Marker(...),
    polygon = new L.Polygon(...),
    rectangle = new L.Rectangle(...),
    circle = new L.Circle(...);

polygon.contains(marker.getLatLng());
rectangle.contains(marker.getLatLng());
circle.contains(marker.getLatLng());

请注意,如果实现polygon方法,则不需要矩形方法。由于矩形从多边形扩展,它将继承该方法。我把它留在那里完成。

Note that if you implement the polygon method that there is no need for the rectangle method. Since rectangle is extended from polygon it will inherit the method. I left it in there to be complete.

现在迭代你的标记并比较它们很容易:

Now iterating your markers and comparing them is easy:

map.on(L.Draw.Event.CREATED, function (e) {
    markers.eachLayer(function (marker) {
        if (!e.layer.contains(marker.getLatLng())) {
            marker.remove();
        }
    });
});

希望有帮助,这是一个工作片段:

Hope that helps, here's a working snippet:

var map = new L.Map('leaflet', {
    'center': [0, 0],
    'zoom': 0
});

var markers = new L.LayerGroup().addTo(map);

for (var i = 0; i < 300; i++) {
    var marker = new L.Marker([
        (Math.random() * (90 - -90) + -90).toFixed(5) * 1,
        (Math.random() * (180 - -180) + -180).toFixed(5) * 1
    ]).addTo(markers);
}

new L.Control.Draw({
    draw: {
        marker   : false,
        polygon  : true,
        polyline : false,
        rectangle: true,
        circle   : {
            metric: 'metric'
        }
    },
    edit: false
}).addTo(map);

L.Polygon.include({
    contains: function (latLng) {
        return turf.inside(new L.Marker(latLng).toGeoJSON(), this.toGeoJSON());
    } 
});

L.Rectangle.include({
    contains: function (latLng) {
        return this.getBounds().contains(latLng);
    }
});

L.Circle.include({
    contains: function (latLng) {
        return this.getLatLng().distanceTo(latLng) < this.getRadius();
    }
});

map.on(L.Draw.Event.CREATED, function (e) {
    markers.eachLayer(function (marker) {
        if (!e.layer.contains(marker.getLatLng())) {
            marker.remove();
        }
    });
});

body {
    margin: 0;
}

html, body, #leaflet {
    height: 100%;
}

<!DOCTYPE html>
<html>
  <head>
    <title>Leaflet 1.0.3</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link type="text/css" rel="stylesheet" href="//unpkg.com/leaflet@1.0.3/dist/leaflet.css" />
    <link type="text/css" rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.9/leaflet.draw.css" />
  </head>
  <body>
    <div id="leaflet"></div>
    <script type="application/javascript" src="//unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
    <script type="application/javascript" src="//cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.9/leaflet.draw.js"></script>
    <script type="application/javascript" src="//unpkg.com/@turf/turf@latest/turf.min.js"></script>
  </body>
</html>

这篇关于如何使用Leaflet.draw获取选择的标记?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆