Leaflet 编辑 GeoJson 数据
Leaflet edit GeoJson Data
我在下面编写了一个代码,用于创建包含一些信息的形状。在我的地图打开之前,我可以编辑这些信息。但是在通过 “将特征导出到本地文件” 更新 geojson 并重新加载页面后,形状仍然无法点击并更正信息我必须删除一些形状并使用适当的参数重新创建它们。
问题:
是否可以在每次打开页面时编辑形状的数据?就像我可以通过 “编辑图层” 按钮编辑形状本身?
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="crossorigin=""/>
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://code.jquery.com/jquery-1.10.2.js" integrity="sha256-it5nQKHTz+34HijZJQkpNBIHsjpV8b6QzMJs9tmOBSo=" crossorigin="anonymous"></script>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#mapid { height: 100% }
</style>
<!--Add draw plugin -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
</script>
<!--Load plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-ajax/2.1.0/leaflet.ajax.min.js"></script>
<style>
#export{
position: absolute;
top:600px;
//right:1800px;
z-index:1000;
background:white;
color:black;
padding:6px;
border-radius:4px;
font-family: 'Helvetica Neue';
cursor: pointer;
font-size:12px;
text-decoration:none;
}
#export {
top:370px;
}
</style>
</head>
<body>
<a href='#' id='export'>Export Features to local file</a>
<div id="mapid"></div>
<script>
var features = "https://api.npoint.io/4fefc36933cc5c22cee4";
var cities = L.layerGroup();
var mbAttr = 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
mbUrl = 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw';
var streets = L.tileLayer(mbUrl, {id: 'mapbox/streets-v11', tileSize: 512, zoomOffset: -1, attribution: mbAttr}),
sat = L.tileLayer('http://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',{
maxZoom: 20,
subdomains:['mt0','mt1','mt2','mt3']
}),
OSM = L.tileLayer('https://maps.jakdojade.pl/osm/{z}/{x}/{y}.png');
Topo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png');
var map = L.map('mapid', {
center: [49.9225,18.99195],
//drawControl: true,
zoom: 8,
layers: [streets, cities]
});
var baseLayers = {
"Podstawowa": streets,
"Satelitarna": sat,
"OSM": OSM,
"Topo": Topo,
};
//SVG2
//SVG2
L.control.layers(baseLayers, {collapsed:false, position:'topleft'}).addTo(map);
</script>
<script>
var featureGroup = new L.GeoJSON.AJAX(features, {
}).addTo(map);
var drawControl = new L.Control.Draw({
edit: {
featureGroup: featureGroup,
}
}).addTo(map);
map.on('draw:created', function (event) {
var layer = event.layer,
feature = layer.feature = layer.feature || {};
feature.type = feature.type || "Feature";
var props = feature.properties = feature.properties || {};
featureGroup.addLayer(layer);
addPopup(layer);
});
var openLayer;
function addPopup(layer){
let popupContent =
'<form>' +
'Link:<br><input type="text" id="input_link"><br>' +
'Cena:<br><input type="text" id="input_cena"><br>' +
'Area:<br><input type="text" id="input_area"><br>' +
'Image:<br><input type="text" id="input_image"><br>' +
'</form>';
layer.on("popupopen", function (e) {
var _layer = e.popup._source;
if(!_layer.feature){
_layer.feature = {
properties: {}
};
}
document.getElementById("input_link").value = _layer.feature.properties.link || "";
document.getElementById("input_cena").value = _layer.feature.properties.cena || "";
document.getElementById("input_area").value = _layer.feature.properties.area || "";
document.getElementById("input_image").value = _layer.feature.properties.image || "";
document.getElementById("input_link").focus();
openLayer = _layer;
});
layer.on("popupclose", function (e) {
openLayer = undefined;
});
layer.bindPopup(popupContent).openPopup();
};
L.DomEvent.on(document,"keyup",function(){
if(openLayer){
link = document.getElementById("input_link").value;
cena = document.getElementById("input_cena").value;
area = document.getElementById("input_area").value;
image = document.getElementById("input_image").value;
openLayer.feature.properties.link = link;
openLayer.feature.properties.cena = cena;
openLayer.feature.properties.area = area;
openLayer.feature.properties.image = image;
openLayer.feature.properties.N = 1;
}
})
document.getElementById('export').onclick = function(e) {
// Extract GeoJson from featureGroup
var data = featureGroup.toGeoJSON();
// Stringify the GeoJson
var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data));
// Create export
document.getElementById('export').setAttribute('href', 'data:' + convertedData);
document.getElementById('export').setAttribute('download','sl.geojson');
};
</script>
</body>
</html>
当然,我做的很快,所以你得适应你自己的代码。
我删除了 L.GeoJSON.AJAX 但没有什么能阻止你继续使用它,我建议你不要这样做 ;)
var features = "https://api.npoint.io/4fefc36933cc5c22cee4";
var cities = L.layerGroup();
var mbAttr =
'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
mbUrl =
"https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw";
var streets = L.tileLayer(mbUrl, {
id: "mapbox/streets-v11",
tileSize: 512,
zoomOffset: -1,
attribution: mbAttr,
});
var map = L.map("mapid", {
center: [49.9225, 18.99195],
zoom: 8,
});
streets.addTo(map);
// add layers to map
async function fetchData(url) {
try {
const response = await fetch(url);
const data = await response.json();
return data;
} catch (err) {
console.error(err);
}
}
fetchData(features).then((geoJsonData) => {
const feature = L.geoJSON(geoJsonData, {
onEachFeature: function(feature, layer) {
layer.on("mouseover", function(e) {
e.target.setStyle({
color: "red",
weight: 2,
});
});
layer.on("mouseout", function(e) {
e.target.setStyle({
color: "#3388ff",
weight: 2,
});
});
addPopup(layer);
},
}).addTo(map);
});
// --------------------------------------------------
// draw section
let drawnItems = L.featureGroup().addTo(map);
map.addControl(
new L.Control.Draw({
edit: {
featureGroup: drawnItems,
poly: {
allowIntersection: false,
},
},
draw: {
polygon: {
allowIntersection: false,
showArea: true,
},
},
})
);
map.on(L.Draw.Event.CREATED, function(event) {
let layer = event.layer;
let feature = (layer.feature = layer.feature || {});
let type = event.layerType;
feature.type = feature.type || "Feature";
let props = (feature.properties = feature.properties || {});
props.type = type;
if (type === "circle") {
props.radius = layer.getRadius();
}
drawnItems.addLayer(layer);
addPopup(layer);
});
var openLayer;
function addPopup(layer) {
let popupContent = `
<form>Link:<br>
<input type="text" id="input_link" value="${
layer.feature.properties.link || ""
}"><br>
Cena:<br><input type="text" id="input_cena" value=${
layer.feature.properties.cena || ""
}><br>
Area:<br><input type="text" id="input_area" value=${
layer.feature.properties.area || ""
}><br>
Image:<br><input type="text" id="input_image" value=${
layer.feature.properties.image || ""
}><br>
</form>`;
layer.on("popupopen", function(e) {
var _layer = e.popup._source;
if (!_layer.feature) {
_layer.feature = {
properties: {},
};
}
// document.getElementById("input_link").value =
// _layer.feature.properties.link || "";
// document.getElementById("input_cena").value =
// _layer.feature.properties.cena || "";
// document.getElementById("input_area").value =
// _layer.feature.properties.area || "";
// document.getElementById("input_image").value =
// _layer.feature.properties.image || "";
// document.getElementById("input_link").focus();
// openLayer = _layer;
});
layer.on("popupclose", function(e) {
openLayer = undefined;
});
layer.bindPopup(popupContent).openPopup();
}
L.DomEvent.on(document, "keyup", function() {
if (openLayer) {
link = document.getElementById("input_link").value;
cena = document.getElementById("input_cena").value;
area = document.getElementById("input_area").value;
image = document.getElementById("input_image").value;
openLayer.feature.properties.link = link;
openLayer.feature.properties.cena = cena;
openLayer.feature.properties.area = area;
openLayer.feature.properties.image = image;
openLayer.feature.properties.N = 1;
}
});
document.getElementById("export").onclick = function(e) {
// Extract GeoJson from featureGroup
var data = featureGroup.toGeoJSON();
// Stringify the GeoJson
var convertedData =
"text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data));
// Create export
document
.getElementById("export")
.setAttribute("href", "data:" + convertedData);
document.getElementById("export").setAttribute("download", "sl.geojson");
};
html {
height: 100%
}
body {
height: 100%;
margin: 0;
padding: 0
}
#mapid {
height: 100%
}
#export {
position: absolute;
top: 600px;
z-index: 1000;
background: white;
color: black;
padding: 6px;
border-radius: 4px;
font-family: 'Helvetica Neue';
cursor: pointer;
font-size: 12px;
text-decoration: none;
}
#export {
top: 370px;
}
<link href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css" rel="stylesheet" />
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
<a href='#' id='export'>Export Features to local file</a>
<div id="mapid"></div>
您可以添加仅在单击编辑按钮时修改字段(表单)的选项。
map.on(L.Draw.Event.EDITED, function (event) {
let layers = event.layers;
layers.eachLayer(function (layer) {
addPopup(layer);
});
});
我在下面编写了一个代码,用于创建包含一些信息的形状。在我的地图打开之前,我可以编辑这些信息。但是在通过 “将特征导出到本地文件” 更新 geojson 并重新加载页面后,形状仍然无法点击并更正信息我必须删除一些形状并使用适当的参数重新创建它们。
问题:
是否可以在每次打开页面时编辑形状的数据?就像我可以通过 “编辑图层” 按钮编辑形状本身?
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="crossorigin=""/>
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://code.jquery.com/jquery-1.10.2.js" integrity="sha256-it5nQKHTz+34HijZJQkpNBIHsjpV8b6QzMJs9tmOBSo=" crossorigin="anonymous"></script>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#mapid { height: 100% }
</style>
<!--Add draw plugin -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
</script>
<!--Load plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-ajax/2.1.0/leaflet.ajax.min.js"></script>
<style>
#export{
position: absolute;
top:600px;
//right:1800px;
z-index:1000;
background:white;
color:black;
padding:6px;
border-radius:4px;
font-family: 'Helvetica Neue';
cursor: pointer;
font-size:12px;
text-decoration:none;
}
#export {
top:370px;
}
</style>
</head>
<body>
<a href='#' id='export'>Export Features to local file</a>
<div id="mapid"></div>
<script>
var features = "https://api.npoint.io/4fefc36933cc5c22cee4";
var cities = L.layerGroup();
var mbAttr = 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
mbUrl = 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw';
var streets = L.tileLayer(mbUrl, {id: 'mapbox/streets-v11', tileSize: 512, zoomOffset: -1, attribution: mbAttr}),
sat = L.tileLayer('http://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',{
maxZoom: 20,
subdomains:['mt0','mt1','mt2','mt3']
}),
OSM = L.tileLayer('https://maps.jakdojade.pl/osm/{z}/{x}/{y}.png');
Topo = L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png');
var map = L.map('mapid', {
center: [49.9225,18.99195],
//drawControl: true,
zoom: 8,
layers: [streets, cities]
});
var baseLayers = {
"Podstawowa": streets,
"Satelitarna": sat,
"OSM": OSM,
"Topo": Topo,
};
//SVG2
//SVG2
L.control.layers(baseLayers, {collapsed:false, position:'topleft'}).addTo(map);
</script>
<script>
var featureGroup = new L.GeoJSON.AJAX(features, {
}).addTo(map);
var drawControl = new L.Control.Draw({
edit: {
featureGroup: featureGroup,
}
}).addTo(map);
map.on('draw:created', function (event) {
var layer = event.layer,
feature = layer.feature = layer.feature || {};
feature.type = feature.type || "Feature";
var props = feature.properties = feature.properties || {};
featureGroup.addLayer(layer);
addPopup(layer);
});
var openLayer;
function addPopup(layer){
let popupContent =
'<form>' +
'Link:<br><input type="text" id="input_link"><br>' +
'Cena:<br><input type="text" id="input_cena"><br>' +
'Area:<br><input type="text" id="input_area"><br>' +
'Image:<br><input type="text" id="input_image"><br>' +
'</form>';
layer.on("popupopen", function (e) {
var _layer = e.popup._source;
if(!_layer.feature){
_layer.feature = {
properties: {}
};
}
document.getElementById("input_link").value = _layer.feature.properties.link || "";
document.getElementById("input_cena").value = _layer.feature.properties.cena || "";
document.getElementById("input_area").value = _layer.feature.properties.area || "";
document.getElementById("input_image").value = _layer.feature.properties.image || "";
document.getElementById("input_link").focus();
openLayer = _layer;
});
layer.on("popupclose", function (e) {
openLayer = undefined;
});
layer.bindPopup(popupContent).openPopup();
};
L.DomEvent.on(document,"keyup",function(){
if(openLayer){
link = document.getElementById("input_link").value;
cena = document.getElementById("input_cena").value;
area = document.getElementById("input_area").value;
image = document.getElementById("input_image").value;
openLayer.feature.properties.link = link;
openLayer.feature.properties.cena = cena;
openLayer.feature.properties.area = area;
openLayer.feature.properties.image = image;
openLayer.feature.properties.N = 1;
}
})
document.getElementById('export').onclick = function(e) {
// Extract GeoJson from featureGroup
var data = featureGroup.toGeoJSON();
// Stringify the GeoJson
var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data));
// Create export
document.getElementById('export').setAttribute('href', 'data:' + convertedData);
document.getElementById('export').setAttribute('download','sl.geojson');
};
</script>
</body>
</html>
当然,我做的很快,所以你得适应你自己的代码。 我删除了 L.GeoJSON.AJAX 但没有什么能阻止你继续使用它,我建议你不要这样做 ;)
var features = "https://api.npoint.io/4fefc36933cc5c22cee4";
var cities = L.layerGroup();
var mbAttr =
'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
mbUrl =
"https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw";
var streets = L.tileLayer(mbUrl, {
id: "mapbox/streets-v11",
tileSize: 512,
zoomOffset: -1,
attribution: mbAttr,
});
var map = L.map("mapid", {
center: [49.9225, 18.99195],
zoom: 8,
});
streets.addTo(map);
// add layers to map
async function fetchData(url) {
try {
const response = await fetch(url);
const data = await response.json();
return data;
} catch (err) {
console.error(err);
}
}
fetchData(features).then((geoJsonData) => {
const feature = L.geoJSON(geoJsonData, {
onEachFeature: function(feature, layer) {
layer.on("mouseover", function(e) {
e.target.setStyle({
color: "red",
weight: 2,
});
});
layer.on("mouseout", function(e) {
e.target.setStyle({
color: "#3388ff",
weight: 2,
});
});
addPopup(layer);
},
}).addTo(map);
});
// --------------------------------------------------
// draw section
let drawnItems = L.featureGroup().addTo(map);
map.addControl(
new L.Control.Draw({
edit: {
featureGroup: drawnItems,
poly: {
allowIntersection: false,
},
},
draw: {
polygon: {
allowIntersection: false,
showArea: true,
},
},
})
);
map.on(L.Draw.Event.CREATED, function(event) {
let layer = event.layer;
let feature = (layer.feature = layer.feature || {});
let type = event.layerType;
feature.type = feature.type || "Feature";
let props = (feature.properties = feature.properties || {});
props.type = type;
if (type === "circle") {
props.radius = layer.getRadius();
}
drawnItems.addLayer(layer);
addPopup(layer);
});
var openLayer;
function addPopup(layer) {
let popupContent = `
<form>Link:<br>
<input type="text" id="input_link" value="${
layer.feature.properties.link || ""
}"><br>
Cena:<br><input type="text" id="input_cena" value=${
layer.feature.properties.cena || ""
}><br>
Area:<br><input type="text" id="input_area" value=${
layer.feature.properties.area || ""
}><br>
Image:<br><input type="text" id="input_image" value=${
layer.feature.properties.image || ""
}><br>
</form>`;
layer.on("popupopen", function(e) {
var _layer = e.popup._source;
if (!_layer.feature) {
_layer.feature = {
properties: {},
};
}
// document.getElementById("input_link").value =
// _layer.feature.properties.link || "";
// document.getElementById("input_cena").value =
// _layer.feature.properties.cena || "";
// document.getElementById("input_area").value =
// _layer.feature.properties.area || "";
// document.getElementById("input_image").value =
// _layer.feature.properties.image || "";
// document.getElementById("input_link").focus();
// openLayer = _layer;
});
layer.on("popupclose", function(e) {
openLayer = undefined;
});
layer.bindPopup(popupContent).openPopup();
}
L.DomEvent.on(document, "keyup", function() {
if (openLayer) {
link = document.getElementById("input_link").value;
cena = document.getElementById("input_cena").value;
area = document.getElementById("input_area").value;
image = document.getElementById("input_image").value;
openLayer.feature.properties.link = link;
openLayer.feature.properties.cena = cena;
openLayer.feature.properties.area = area;
openLayer.feature.properties.image = image;
openLayer.feature.properties.N = 1;
}
});
document.getElementById("export").onclick = function(e) {
// Extract GeoJson from featureGroup
var data = featureGroup.toGeoJSON();
// Stringify the GeoJson
var convertedData =
"text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data));
// Create export
document
.getElementById("export")
.setAttribute("href", "data:" + convertedData);
document.getElementById("export").setAttribute("download", "sl.geojson");
};
html {
height: 100%
}
body {
height: 100%;
margin: 0;
padding: 0
}
#mapid {
height: 100%
}
#export {
position: absolute;
top: 600px;
z-index: 1000;
background: white;
color: black;
padding: 6px;
border-radius: 4px;
font-family: 'Helvetica Neue';
cursor: pointer;
font-size: 12px;
text-decoration: none;
}
#export {
top: 370px;
}
<link href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css" rel="stylesheet" />
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js"></script>
<a href='#' id='export'>Export Features to local file</a>
<div id="mapid"></div>
您可以添加仅在单击编辑按钮时修改字段(表单)的选项。
map.on(L.Draw.Event.EDITED, function (event) {
let layers = event.layers;
layers.eachLayer(function (layer) {
addPopup(layer);
});
});