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

蓝咒 提交于 2019-12-17 17:04:50

问题


I am trying to use leaflet's edit function on polygons that I loaded from my database. When I click on leaflet's edit button I get the error
Cannot read property 'enable' of undefined

This thread describes a similar problem, and user ddproxy said

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

I am confused what he means by "walk through", I thought I was adding a layer group, so i'm not sure what I would be walking through. Does this have to do with the fact that i'm adding the polygons as a geoJSON object?
Adding the polygons to the map, binding their popups, and assigning them custom colors works perfectly FYI.

The following is the relevant code:

<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>

And the loadHazards() function:

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

    }
});
}

Thanks in advance!


回答1:


Unfortunately Leaflet.draw plugin does not handle nested Layer Groups (same for Feature Groups / GeoJSON Layer Groups).

That is the meaning of the 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 method). If the child layer is a non-group layer, then add it to your editable Feature Group. If it is another nested group, then loop through its own child layers again.

See the code proposed in that 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);
  }
}

In your very case, you can also refactor your code with 2 other solutions:

  • Instead of building your layerGroup (which is actually a 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 for each of your single Features (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
}
  • Instead of building a GeoJSON Feature Object (item) and parse it into a Leaflet GeoJSON Layer, you can directly build a Leaflet Polygon and add it into your Hazards Layer/Feature Group:
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"};
  }
}



回答2:


As mentioned by @ghybs Leaflet.Draw doesn't support Groups or MultiPolygons. I needed the same functionality so a few years ago I created leaflet.pm which supports holes, MultiPolygons, GeoJSON and LayerGroups:

https://github.com/codeofsumit/leaflet.pm

Hope it helps.



来源:https://stackoverflow.com/questions/53463078/leaflet-draw-cannot-read-property-enable-of-undefined-adding-control-to-geoj

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!