Tom*_*Tom 3 javascript leaflet leaflet.draw
我正在尝试对从数据库加载的多边形使用传单的编辑功能。当我单击传单的编辑按钮时,出现错误
Cannot read property 'enable' of undefined
该线程描述了类似的问题,并且用户ddproxy表示
“由于FeatureGroup扩展了LayerGroup,因此您可以遍历显示的图层并将其分别添加到用于Leaflet.draw的FeatureGroup中”
我对他所说的“遍历”感到困惑,我以为我要添加一个图层组,所以我不确定我要遍历什么。这是否与我将多边形添加为geoJSON对象这一事实有关?
将多边形添加到地图,绑定其弹出窗口并为它们分配自定义颜色可以完美地实现FYI。
以下是相关代码:
<script>
window.addEventListener("load", function(event){
//other stuff
loadHazards();
});
//next 6 lines siply add map to page
var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
var osmAttrib = '© <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors'
var osm = L.tileLayer(osmUrl, { maxZoom: 18, attribution: osmAttrib})
var map = new L.Map('map', { center: new L.LatLng(39.255467, -76.711964), zoom: 16 })
osm.addTo(map);
var drawnItems = L.featureGroup().addTo(map);
var Hazards = L.featureGroup().addTo(map);
L.control.layers({
'osm': osm.addTo(map)
},
{
'drawlayer': drawnItems,
"Hazards" : Hazards,
"Tickets": Tickets
},
{
position: 'topleft', collapsed: false
}
).addTo(map);
map.addControl(new L.Control.Draw({
edit: {
featureGroup: Hazards,
poly: {
allowIntersection: false
}
},
draw: {
polygon: {
allowIntersection: false,
showArea: true
},
rectangle:false,
circle:false,
circlemarker:false
}
}));
map.on(L.Draw.Event.CREATED, function (event) {
var layer = event.layer;
drawnItems.addLayer(layer);
});
</script>
Run Code Online (Sandbox Code Playgroud)
和loadHazards()函数:
function loadHazards(){
$.ajax({
type: 'GET',
url:'/loadPolygonFromDatabase',
success : function(polygons){
polygons = JSON.parse(polygons);
var toAdd = [];
for (i in polygons){
var item = {
"type" : "Feature",
"properties":{
"category":"",
"description":"",
"ID":""
},
"geometry" : {
"type":"Polygon",
"coordinates":[],
}
};
item["geometry"]["coordinates"][0] = polygons[i]["coordinates"];
item["properties"]["category"] = polygons[i]["category"];
item["properties"]["description"] = polygons[i]["description"];
item["properties"]["ID"] = polygons[i]["ID"];
toAdd.push(item);
}
//Add information to popup
var layerGroup = L.geoJSON(toAdd, {
onEachFeature: function (feature, layer) {
layer.bindPopup( '<h1>' + feature.properties.category + '</h1>'
+ '<p>' + feature.properties.description + '</p>');
layer.id = feature.properties.ID;
},
style: function(feature){
switch (feature.properties.category) {
case 'Rabid_Beavers': return {color: "#663326"};
case 'Fire': return {color: "#ff0000"};
case 'Flood': return {color: "#0000ff"};
}
}
}).addTo(Hazards);
}
});
}
Run Code Online (Sandbox Code Playgroud)
提前致谢!
正如@ghybs 所提到的那样,Leaflet.Draw 不支持 Groups 或 MultiPolygons。我需要相同的功能,所以几年前我创建了 Leaflet-Geoman(以前称为 Leaflet.pm),它支持孔、MultiPolygons、GeoJSON 和 LayerGroups:
https://github.com/geoman-io/leaflet-geoman
希望能帮助到你。
不幸的是,Leaflet.draw插件无法处理嵌套的图层组(与要素组/ GeoJSON图层组相同)。
那就是您参考的Leaflet.draw#398问题的含义:他们建议循环遍历您的Layer / Feature / GeoJSON Layer Group 的子层(例如,使用其eachLayer方法)。如果子图层是非图层图层,则将其添加到可编辑的要素组中。如果它是另一个嵌套组,则再次遍历其自己的子层。
请参阅该帖子中建议的代码:
https://gis.stackexchange.com/questions/203540/how-to-edit-an-existing-layer-using-leaflet
var geoJsonGroup = L.geoJson(myGeoJSON);
addNonGroupLayers(geoJsonGroup, drawnItems);
// Would benefit from https://github.com/Leaflet/Leaflet/issues/4461
function addNonGroupLayers(sourceLayer, targetGroup) {
if (sourceLayer instanceof L.LayerGroup) {
sourceLayer.eachLayer(function(layer) {
addNonGroupLayers(layer, targetGroup);
});
} else {
targetGroup.addLayer(sourceLayer);
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您还可以使用其他两种解决方案来重构代码:
layerGroup(实际上是一个Leaflet GeoJSON图层组),然后再将其添加到您的Hazards要素组中,不如从一开始就addData针对每个单独的Features(item)将后者设为GeoJSON Layer Group :var Hazards = L.geoJSON(null, yourOptions).addTo(map);
for (i in polygons) {
var item = {
"type" : "Feature",
// etc.
};
// toAdd.push(item);
Hazards.addData(item); // Directly add the GeoJSON Feature object
}
Run Code Online (Sandbox Code Playgroud)
item)并将其解析为Leaflet GeoJSON图层,您可以直接构建Leaflet Polygon并将其添加到您的HazardsLayer / Feature组中:for (i in polygons) {
var coords = polygons[i]["coordinates"];
var style = getStyle(polygons[i]["category"]);
var popup = ""; // fill it as you wish
// Directly build a Leaflet layer instead of an intermediary GeoJSON Feature
var itemLayer = L.polygon(coords, style).bindPopup(popup);
itemLayer.id = polygons[i]["ID"];
itemLayer.addTo(Hazards);
}
function getStyle(category) {
switch (category) {
case 'Rabid_Beavers': return {color: "#663326"};
case 'Fire': return {color: "#ff0000"};
case 'Flood': return {color: "#0000ff"};
}
}
Run Code Online (Sandbox Code Playgroud)