Leaflet Draw "Cannot read property 'enable' of undefined" 向 geoJSON 层添加控件

Leaflet Draw "Cannot read property 'enable' of undefined" adding control to geoJSON layer

我正在尝试对从数据库加载的多边形使用传单的编辑功能。当我点击传单的编辑按钮时,出现错误
Cannot read property 'enable' of undefined

This thread描述了类似的问题,用户ddproxy说

"Since FeatureGroup extends LayerGroup You can walk through the layers presented and add them individually to the FeatureGroup used for Leaflet.draw"

我不明白他所说的 "walk through" 是什么意思,我以为我在添加一个图层组,所以我不确定我会经过什么。这是否与我将多边形添加为 geoJSON 对象有关?
将多边形添加到地图,绑定它们的弹出窗口,并为它们分配自定义颜色,仅供参考。

相关代码如下:

<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 = '&copy; <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>

和 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);

    }
});
}

提前致谢!

不幸的是 Leaflet.draw 插件不处理嵌套图层组(功能组/GeoJSON 图层组也是如此)。

也就是Leaflet.draw #398 issue you reference: they advise looping through the child layers of your Layer/Feature/GeoJSON Layer Group (e.g. with their eachLayer方法的意思)。如果子层是非组层,则将其添加到可编辑的要素组中。如果是另一个嵌套组,则再次循环自己的子层。

参见post中提出的代码:

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);
  }
}

对于您的情况,您还可以使用其他 2 种解决方案重构您的代码:

  • 而不是构建你的 layerGroup(这实际上是一个 Leaflet GeoJSON Layer Group) first and then add it into your Hazards Feature Group, make the latter a GeoJSON Layer Group from the beginning, and addData 为你的每个单一功能(item):
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
}
  • 无需构建 GeoJSON 要素对象 (item) 并将其解析为 Leaflet GeoJSON 层,您可以直接构建 Leaflet Polygon 并将其添加到您的 Hazards Layer/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"};
  }
}

如@ghybs 所述,Leaflet.Draw 不支持组或多边形。我需要相同的功能,所以几年前我创建了 Leaflet-Geoman(以前名为 leaflet.pm),它支持孔、MultiPolygons、GeoJSON 和 LayerGroups:

https://github.com/geoman-io/leaflet-geoman

希望对您有所帮助。