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 = '© <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
希望对您有所帮助。
我正在尝试对从数据库加载的多边形使用传单的编辑功能。当我点击传单的编辑按钮时,出现错误
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 = '© <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 yourHazards
Feature Group, make the latter a GeoJSON Layer Group from the beginning, andaddData
为你的每个单一功能(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
希望对您有所帮助。