問(wèn)題描述
上下文:
我制作了一張地圖,并在其中填充了大約 300 個(gè)隨機(jī)標(biāo)記.我可以通過(guò)單擊彈出窗口中的鏈接來(lái)選擇"標(biāo)記并激活選擇以顯示數(shù)據(jù).我還有 Leaflet.draw 插件來(lái)繪制圓形、矩形和自定義形狀等形狀,我想用它來(lái)選擇"幾個(gè)標(biāo)記.
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.
問(wèn)題
如何獲取落入已繪制的 leaflet.draw 形狀內(nèi)的標(biāo)記的傳單標(biāo)記對(duì)象,以便編輯它們?我似乎無(wú)法進(jìn)行選擇,它要么不選擇任何標(biāo)記,要么全部選擇.
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 的實(shí)用方法可以很容易地完成大部分您想要的事情.如果你想用像 L.Polygon
這樣的復(fù)雜形狀來(lái)做到這一點(diǎn),你需要像 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
對(duì)于L.Circle
,您需要計(jì)算圓心之間的距離并將其與半徑進(jìn)行比較:
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();
對(duì)于 L.Rectangle
你需要獲取它的邊界對(duì)象并使用 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());
正如對(duì)于復(fù)雜多邊形所說(shuō),我使用的是 Turf,但那里有更多的庫(kù)和插件.這是一個(gè)使用 Turf 的 inside
方法的示例.它采用 GeoJSON 點(diǎn)和多邊形特征作為參數(shù),因此請(qǐng)注意轉(zhuǎn)換:
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());
您可以將它們包裝到每個(gè)相應(yīng)類的便利方法中:
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());
請(qǐng)注意,如果您實(shí)現(xiàn)了多邊形方法,則不需要矩形方法.由于矩形是從多邊形擴(kuò)展而來(lái)的,它將繼承該方法.我把它放在那里是為了完成.
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.
現(xiàn)在迭代你的標(biāo)記并比較它們很容易:
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();
}
});
});
希望對(duì)您有所幫助,這是一個(gè)有效的片段:
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" />
<link type="text/css" rel="stylesheet" />
</head>
<body>
<div id="leaflet"></div>
<script type="application/javascript" src="http://unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
<script type="application/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.9/leaflet.draw.js"></script>
<script type="application/javascript" src="http://unpkg.com/@turf/turf@latest/turf.min.js"></script>
</body>
</html>
這篇關(guān)于如何使用 Leaflet.draw 抓取一系列標(biāo)記?的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!