就地更新 Leaflet GeoJSON 功能
in-place Update Leaflet GeoJSON feature
我希望 GeoJSON.addData() 会 return GeoJSON 对象的新创建的子层,但事实并非如此。为什么我需要这样的东西?
(目前使用 Leaflet 1.0Beta2)
我正在使用 Leaflet GeoJson 在 GeoJSON(点、线、多边形)中显示实时数据。它是一个 CRUD 接口(创建、更新和删除)。我收到带有 GeoJSON 数据的 WebSocket 消息,每个消息都有一个 GUID。
在 CREATE 的情况下,我只是对适当的层执行 GeoJSon.AddData()。
但是对于 UPDATE 和 DELETE 我想要一个添加到 GeoJSON 的层的句柄,以便我可以更新它位置,或更新几何。 addData 没有给我这个句柄。而且很难从 onEachFeature() 或 pointToLayer()
得到它
目前,我确实有一个可行但丑陋的方法。我要做的就是用 GeoJSon.eachLayer(fn) 搜索整个图层
每当发生更新或删除时。好像有点贵。
{即使 Leaflet 并不是真正为这种实时 r/t 数据显示而设计的,它也在工作,如果你不能用它来观察大量传感器数据,这似乎很难过,物联网)因为我们正在做。
this.delete = function (layerName, feature) {
if (!(layerName in self.myLayers)) {
alert("live.display: Missing Layer: " + layerName);
return;
}
var layerInfo = Live.myLayers[layerName];
var base = layerInfo.layer;
var id = feature.properties.objectID;
this.find(layerName, id, function (layer) {
this.removeLayer(layer);
Tools.debug(16, "live.delete:", "killed object: " + id);
});
}
this.find = function (layerName, id, action) {
var base = Live.myLayers[layerName].layer;
base.eachLayer(function (feature) {
if (!("objectID" in feature.feature.properties)) { return; }
var objectID = feature.feature.properties.objectID;
if (objectID == id) {
action.call(base, feature);
}
});
}
而不是(或并行地)"merging" 所有创建的 GeoJSON 特征都放入单个 Leaflet GeoJSON 图层组中(你用 addData
做),为什么不先在自己的 Leaflet 中创建每个特征GeoJSON 层,以便它为您提供您正在寻找的句柄(然后您可以简单地将此句柄记录在对象/映射中,例如键是您的 objectID
)?
如果需要,您甚至可以在此之后将各个图层合并到单个 GeoJSON 图层组中。
var myGeoJsonLayerGroup = L.geoJson().addTo(map);
var myFeaturesMap = {};
function addNewFeatureToGeoJsonLayerGroup(newGeoJsonData) {
var newGeoJSONfeature = L.geoJson(newGeoJsonData);
myFeaturesMap[newGeoJsonData.properties.objectID] = newGeoJSONfeature;
myGeoJsonLayerGroup.addLayer(newGeoJSONfeature);
}
function updateFeature(updatedGeoJsonData) {
var updatedFeature = myFeaturesMap[updatedGeoJsonData.properties.objectID];
updatedFeature.clearLayers(); // Remove the previously created layer.
updatedFeature.addData(updatedGeoJsonData); // Replace it by the new data.
}
function deleteFeature(deletedGeoJsonData) {
var deletedFeature = myFeaturesMap[deletedGeoJsonData.properties.objectID];
myGeoJsonLayerGroup.removeLayer(deletedFeature);
}
演示(不使用 GeoJSON):http://jsfiddle.net/ve2huzxw/94/
编辑:
一个稍微简单的解决方案是通过 GeoJSON 层组的 onEachFeature
函数存储对每个单独层的引用:
var myFeaturesMap = {};
var myGeoJsonLayerGroup = L.geoJson({
onEachFeature: function (feature, layer) {
myFeaturesMap[feature.properties.objectID] = layer;
}
}).addTo(map);
function addNewFeatureToGeoJsonLayerGroup(newGeoJsonData) {
myGeoJsonLayerGroup.addData(newGeoJsonData);
}
function updateFeature(updatedGeoJsonData) {
deleteFeature(updatedGeoJsonData); // Remove the previously created layer.
addNewFeatureToGeoJsonLayerGroup(updatedGeoJsonData); // Replace it by the new data.
}
function deleteFeature(deletedGeoJsonData) {
var deletedFeature = myFeaturesMap[deletedGeoJsonData.properties.objectID];
myGeoJsonLayerGroup.removeLayer(deletedFeature);
}
如果您想存储对正在创建的实际层的引用,您可以从 L.GeoJSON
实例上的 layeradd
事件访问它们:
var geojson = new L.GeoJSON().on(
'layeradd', function (e) {
console.log(e.layer);
}
).addTo(map);
// This addData call will fire the handler above twice
// because it adds two features.
geojson.addData({
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [90, 0]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [-90, 0]
}
}]
});
如果有人仍在寻找另一种更新的简短方法GeoJSON
,您可以尝试这样的方法,
//function to clear the previous geojson feature
function clearMap() {
map.eachLayer(function(layer){
if(layer.myTag && layer.myTag === 'previousLayer'){
lmap.removeLayer(layer);
}
});
}
function geojsonUpdate(geojsonData){
var geojsonLayer = L.geoJson(geojsonData, {
onEachFeature: function (feature, layer) {
layer.myTag = 'previousLayer'
);
},
});
geojsonLayer.addTo(lmap);
lmap.fitBounds(geojsonLayer.getBounds());
}
//function call
clearMap();
geojsonUpdate(data);
我希望 GeoJSON.addData() 会 return GeoJSON 对象的新创建的子层,但事实并非如此。为什么我需要这样的东西?
(目前使用 Leaflet 1.0Beta2)
我正在使用 Leaflet GeoJson 在 GeoJSON(点、线、多边形)中显示实时数据。它是一个 CRUD 接口(创建、更新和删除)。我收到带有 GeoJSON 数据的 WebSocket 消息,每个消息都有一个 GUID。
在 CREATE 的情况下,我只是对适当的层执行 GeoJSon.AddData()。
但是对于 UPDATE 和 DELETE 我想要一个添加到 GeoJSON 的层的句柄,以便我可以更新它位置,或更新几何。 addData 没有给我这个句柄。而且很难从 onEachFeature() 或 pointToLayer()
得到它目前,我确实有一个可行但丑陋的方法。我要做的就是用 GeoJSon.eachLayer(fn) 搜索整个图层 每当发生更新或删除时。好像有点贵。
{即使 Leaflet 并不是真正为这种实时 r/t 数据显示而设计的,它也在工作,如果你不能用它来观察大量传感器数据,这似乎很难过,物联网)因为我们正在做。
this.delete = function (layerName, feature) {
if (!(layerName in self.myLayers)) {
alert("live.display: Missing Layer: " + layerName);
return;
}
var layerInfo = Live.myLayers[layerName];
var base = layerInfo.layer;
var id = feature.properties.objectID;
this.find(layerName, id, function (layer) {
this.removeLayer(layer);
Tools.debug(16, "live.delete:", "killed object: " + id);
});
}
this.find = function (layerName, id, action) {
var base = Live.myLayers[layerName].layer;
base.eachLayer(function (feature) {
if (!("objectID" in feature.feature.properties)) { return; }
var objectID = feature.feature.properties.objectID;
if (objectID == id) {
action.call(base, feature);
}
});
}
而不是(或并行地)"merging" 所有创建的 GeoJSON 特征都放入单个 Leaflet GeoJSON 图层组中(你用 addData
做),为什么不先在自己的 Leaflet 中创建每个特征GeoJSON 层,以便它为您提供您正在寻找的句柄(然后您可以简单地将此句柄记录在对象/映射中,例如键是您的 objectID
)?
如果需要,您甚至可以在此之后将各个图层合并到单个 GeoJSON 图层组中。
var myGeoJsonLayerGroup = L.geoJson().addTo(map);
var myFeaturesMap = {};
function addNewFeatureToGeoJsonLayerGroup(newGeoJsonData) {
var newGeoJSONfeature = L.geoJson(newGeoJsonData);
myFeaturesMap[newGeoJsonData.properties.objectID] = newGeoJSONfeature;
myGeoJsonLayerGroup.addLayer(newGeoJSONfeature);
}
function updateFeature(updatedGeoJsonData) {
var updatedFeature = myFeaturesMap[updatedGeoJsonData.properties.objectID];
updatedFeature.clearLayers(); // Remove the previously created layer.
updatedFeature.addData(updatedGeoJsonData); // Replace it by the new data.
}
function deleteFeature(deletedGeoJsonData) {
var deletedFeature = myFeaturesMap[deletedGeoJsonData.properties.objectID];
myGeoJsonLayerGroup.removeLayer(deletedFeature);
}
演示(不使用 GeoJSON):http://jsfiddle.net/ve2huzxw/94/
编辑:
一个稍微简单的解决方案是通过 GeoJSON 层组的 onEachFeature
函数存储对每个单独层的引用:
var myFeaturesMap = {};
var myGeoJsonLayerGroup = L.geoJson({
onEachFeature: function (feature, layer) {
myFeaturesMap[feature.properties.objectID] = layer;
}
}).addTo(map);
function addNewFeatureToGeoJsonLayerGroup(newGeoJsonData) {
myGeoJsonLayerGroup.addData(newGeoJsonData);
}
function updateFeature(updatedGeoJsonData) {
deleteFeature(updatedGeoJsonData); // Remove the previously created layer.
addNewFeatureToGeoJsonLayerGroup(updatedGeoJsonData); // Replace it by the new data.
}
function deleteFeature(deletedGeoJsonData) {
var deletedFeature = myFeaturesMap[deletedGeoJsonData.properties.objectID];
myGeoJsonLayerGroup.removeLayer(deletedFeature);
}
如果您想存储对正在创建的实际层的引用,您可以从 L.GeoJSON
实例上的 layeradd
事件访问它们:
var geojson = new L.GeoJSON().on(
'layeradd', function (e) {
console.log(e.layer);
}
).addTo(map);
// This addData call will fire the handler above twice
// because it adds two features.
geojson.addData({
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [90, 0]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [-90, 0]
}
}]
});
如果有人仍在寻找另一种更新的简短方法GeoJSON
,您可以尝试这样的方法,
//function to clear the previous geojson feature
function clearMap() {
map.eachLayer(function(layer){
if(layer.myTag && layer.myTag === 'previousLayer'){
lmap.removeLayer(layer);
}
});
}
function geojsonUpdate(geojsonData){
var geojsonLayer = L.geoJson(geojsonData, {
onEachFeature: function (feature, layer) {
layer.myTag = 'previousLayer'
);
},
});
geojsonLayer.addTo(lmap);
lmap.fitBounds(geojsonLayer.getBounds());
}
//function call
clearMap();
geojsonUpdate(data);