【问题标题】:Leaflet Draw "Cannot read property 'enable' of undefined" adding control to geoJSON layerLeaflet Draw“无法读取未定义的属性'启用'”向geoJSON图层添加控件
【发布时间】:2018-11-24 22:55:10
【问题描述】:

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

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

“由于FeatureGroup扩展了LayerGroup,你可以遍历图层 呈现并将它们单独添加到用于 Leaflet.draw"

我很困惑他所说的“穿行”是什么意思,我以为我是在添加一个图层组,所以我不确定我会穿行什么。这是否与我将多边形添加为 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);

    }
});
}

提前致谢!

【问题讨论】:

    标签: javascript leaflet leaflet.draw


    【解决方案1】:

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

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

    希望对你有帮助。

    【讨论】:

    • leaflet.pm 非常好。在用 Leaflet.Draw 和 GeoJSON FeatureCollections of MultiPolygons 将我的头撞到墙上后,我切换到它。
    【解决方案2】:

    不幸的是,Leaflet.draw 插件不处理嵌套层组(特征组/GeoJSON 层组相同)。

    这就是您引用的Leaflet.draw #398 问题的含义:他们建议循环遍历您的 Layer/Feature/GeoJSON 层组的 child 层(例如,使用他们的 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);
      }
    }
    

    在您的情况下,您还可以使用 2 个其他解决方案重构您的代码:

    • 不要先构建layerGroup(实际上是Leaflet GeoJSON Layer Group),然后将其添加到Hazards 功能组中,而是从一开始就将后者设置为GeoJSON 层组,并为每个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 层/特征组中:
    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"};
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-02-24
      • 1970-01-01
      • 1970-01-01
      • 2022-01-27
      • 2021-10-05
      • 2021-07-24
      • 2018-02-06
      • 1970-01-01
      相关资源
      最近更新 更多