传单绘制“无法读取未定义的属性'启用'”将控件添加到geoJSON层

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 = '&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>
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)

提前致谢!

Pro*_*mit 8

正如@ghybs 所提到的那样,Leaflet.Draw 不支持 Groups 或 MultiPolygons。我需要相同的功能,所以几年前我创建了 Leaflet-Geoman(以前称为 Leaflet.pm),它支持孔、MultiPolygons、GeoJSON 和 LayerGroups:

在此处输入图片说明

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

希望能帮助到你。

  • Leaflet.pm 非常好。在使用 Leaflet.Draw 和 GeoJSON FeatureCollections of MultiPolygons 撞墙后,我切换到它。 (5认同)

ghy*_*ybs 5

不幸的是,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)
  • 无需构建GeoJSON Feature Object(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)