向 LeafletJs 地图添加叠加层正在更改数据,我不知道为什么
Adding overlay to LeafletJs map is changing data, and I have no idea why
所以我的团队正在开发一个使用 LeafletJs 的 Web 应用程序,并且需要导入和导出应用程序中生成的数据。这包括覆盖率数据。我们已经 运行 进入(看起来像)一个错误,我们正在导入和导出的数据正在被传单中的事件更改,我们不知道为什么。
我已经在 Codepen 中制作了一些东西(第一次使用它,如果有任何问题,请见谅)以尽可能地隔离问题。
Codepen
娱乐步骤
打开 web 应用程序并单击“导出”(并根据浏览器的行为进行保存。如果你想在下载前检查它,你应该有一个看起来像 Codepen 的 JS 文件中的对象的 JSON 文件来自 st运行ger 的东西。这个文件应该可以正常工作。
现在单击 TEMP 将叠加层添加到 Leaflet 地图。这是以某种方式破坏数据的操作。如果您再次单击“导出”,您将得到一个不起作用的不同文件。
如果您导入第一个文件,然后单击新添加的复选框,它将很好地添加覆盖。
如果您导入第二个文件,它将导入而不会出现错误,但如果您尝试使用复选框将其添加为覆盖,则会失败。如果你比较这两个 JSON 文件,它们是完全不同的。虽然他们应该完全一样。
绝对是将数据添加到地图的行为造成了这些变化,因为删除它并导出结果是同一个变异的 JSON 文件,而不是返回原始文件。
源代码
HTML
<!DOCTYPE html>
<meta charset="UTF-8">
<html lang="en">
<head>
<title>Demo</title>
<link rel="stylesheet" type="text/css" href="index.css">
<!-- Leaflet.core -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin="">
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossorigin=""></script>
<!-- CoverageJSON Reader -->
<script src="https://unpkg.com/covutils/covutils-lite.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/covjson-reader/0.16.3/covjson-reader.min.js"
integrity="sha512-n8pZdTvMgAYZSgA0zOjItMZKeSEkQkxWJkVAAV3VMmmmGdEX5EHbqIYF0fuWYHPvKrz4X7fryuYcuR0ows9Ohw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<!-- Leaflet Coverage -->
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.1/leaflet.css">
<link rel="stylesheet" type="text/css" href="https://unpkg.com/leaflet-coverage@0.7/leaflet-coverage.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.1/leaflet.js"></script>
<script src="https://unpkg.com/covutils@0.6/covutils.min.js"></script>
<script src="https://unpkg.com/leaflet-coverage@0.7/leaflet-coverage.min.js"></script>
</head>
<body>
<a id="dataExport">
<button id="exportButton" onclick="exportData()">Export</button>
</a>
<label id="importLabel" for="dataImport">Import</label>
<input id="dataImport" type="file" name="dataImport" onchange="importData()"/>
<div class='map' id="map"></div>
</body>
<script src="index.js"></script>
</html>
JS
const baseLayer = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'});
const bounds = [[48, -12,], [61.5, 3]];
const map = L.map('map', {
layers: [baseLayer],
maxBounds: bounds,
maxBoundsViscosity: 0.9,
}).setView([((bounds[1][0] + bounds[0][0]) / 2), ((bounds[1][1] + bounds[0][1]) / 2)], 5);
const controlLayers = L.control.layers({"OSM": baseLayer}, undefined, {collapsed: false}).addTo(map);
const dataArray = [];
loadCoverageData(mockData); // Mocking a fetch and response
function loadCoverageData(data) {
console.log("Attempting to load: \n", data);
dataArray.push(data) // User could have multiple layers of
CovJSON.read(data)
.then((coverage) => {
let dataLayer = C.dataLayer(coverage, {parameter: Object.keys(data.parameters)[0]})
.on('afterAdd', () => {
if (dataLayer.palette) {
C.legend(dataLayer).addTo(map)
}
if (dataLayer.timeSlices) {
new C.TimeAxis(dataLayer).addTo(map)
}
})
controlLayers.addOverlay(dataLayer, Object.keys(data.parameters)[0]);
});
}
function replacer(key, value) {
if (value instanceof Map) {
return {
dataType: 'Map',
value: Array.from(value.entries()),
};
} else {
return value;
}
}
function reviver(key, value) {
if (typeof value === 'object' && value !== null) {
if (value.dataType === 'Map') {
return new Map(value.value);
}
}
return value;
}
function exportData() {
let encodedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(dataArray, replacer));
document.getElementById('dataExport').setAttribute('href', 'data:' + encodedData);
document.getElementById('dataExport').setAttribute('download', 'drawing-data.json');
}
function importData() {
let dataFile = document.getElementById('dataImport').files[0]
let reader = new FileReader();
reader.onload = function (event) {
let data = JSON.parse(event.target.result, reviver);
data.forEach((coverageSet) => {
loadCoverageData(coverageSet);
})
}
reader.readAsText(dataFile);
}
const mockData = {
"type": "Coverage",
"domain": {
"type": "Domain",
"domainType": "MultiPolygon",
"axes": {
"composite": {
"dataType": "polygon",
"coordinates": [
"x",
"y"
],
"values": [
[
[
[
9.92,
54.98
],
[
9.93,
54.59
],
[
13.64,
54.07
],
[
15.01,
51.10
],
[
12.24,
50.26
],
[
12.52,
49.54
],
[
13.59,
48.87
],
[
12.88,
48.28
],
[
13.02,
47.63
],
[
9.59,
47.52
],
[
8.52,
47.83
],
[
7.46,
47.62
],
[
8.09,
49.01
],
[
6.18,
49.46
],
[
5.98,
51.85
],
[
6.84,
52.22
],
[
7.10,
53.69
],
[
8.80,
54.02
],
[
8.52,
54.96
],
[
9.92,
54.98
]
]
],
[
[
[
-3.00,
58.63
],
[
-1.95,
57.68
],
[
-2.08,
55.90
],
[
0.46,
52.92
],
[
1.68,
52.73
],
[
0.55,
50.76
],
[
-3.61,
50.22
],
[
-5.26,
51.99
],
[
-3.63,
54.61
],
[
-5.58,
55.31
],
[
-6.14,
56.78
],
[
-5.00,
58.63
],
[
-3.00,
58.63
]
]
]
]
},
"t": {
"values": [
"2015"
]
}
},
"referencing": [
{
"coordinates": [
"x",
"y"
],
"system": {
"type": "GeographicCRS",
"id": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
}
},
{
"coordinates": [
"t"
],
"system": {
"type": "TemporalRS",
"calendar": "Gregorian"
}
}
]
},
"parameters": {
"TEMP": {
"type": "Parameter",
"unit": {
"label": {
"en": "Degree Celsius"
},
"symbol": {
"value": "Cel",
"type": "http://www.opengis.net/def/uom/UCUM/"
}
},
"observedProperty": {
"label": {
"en": "Average air temperature"
}
}
}
},
"ranges": {
"TEMP": {
"type": "NdArray",
"dataType": "float",
"axisNames": [
"composite"
],
"shape": [
2
],
"values": [
22.8,
15.1
]
}
}
}
CS
.map {
height: 80vh;
width: 80vw;
}
由于在 loadCoverageData
中的 CovJSON.read(data)
中使用了 data
,因此 javascript 引用仍然存在并且被动态覆盖/修改:
function loadCoverageData(data) {
console.log("Attempting to load: \n", data);
dataArray.push(data) // User could have multiple layers of
CovJSON.read(data).then((coverage) => {
简单地“复制”数据对象并中断引用。一种解决方案是使用 data = JSON.parse(JSON.stringify(data))
:
function loadCoverageData(data) {
console.log("Attempting to load: \n", data);
dataArray.push(data) // User could have multiple layers of
data = JSON.parse(JSON.stringify(data))
CovJSON.read(data).then((coverage) => {
所以我的团队正在开发一个使用 LeafletJs 的 Web 应用程序,并且需要导入和导出应用程序中生成的数据。这包括覆盖率数据。我们已经 运行 进入(看起来像)一个错误,我们正在导入和导出的数据正在被传单中的事件更改,我们不知道为什么。
我已经在 Codepen 中制作了一些东西(第一次使用它,如果有任何问题,请见谅)以尽可能地隔离问题。
Codepen
娱乐步骤
打开 web 应用程序并单击“导出”(并根据浏览器的行为进行保存。如果你想在下载前检查它,你应该有一个看起来像 Codepen 的 JS 文件中的对象的 JSON 文件来自 st运行ger 的东西。这个文件应该可以正常工作。
现在单击 TEMP 将叠加层添加到 Leaflet 地图。这是以某种方式破坏数据的操作。如果您再次单击“导出”,您将得到一个不起作用的不同文件。
如果您导入第一个文件,然后单击新添加的复选框,它将很好地添加覆盖。
如果您导入第二个文件,它将导入而不会出现错误,但如果您尝试使用复选框将其添加为覆盖,则会失败。如果你比较这两个 JSON 文件,它们是完全不同的。虽然他们应该完全一样。
绝对是将数据添加到地图的行为造成了这些变化,因为删除它并导出结果是同一个变异的 JSON 文件,而不是返回原始文件。
源代码
HTML
<!DOCTYPE html>
<meta charset="UTF-8">
<html lang="en">
<head>
<title>Demo</title>
<link rel="stylesheet" type="text/css" href="index.css">
<!-- Leaflet.core -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin="">
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossorigin=""></script>
<!-- CoverageJSON Reader -->
<script src="https://unpkg.com/covutils/covutils-lite.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/covjson-reader/0.16.3/covjson-reader.min.js"
integrity="sha512-n8pZdTvMgAYZSgA0zOjItMZKeSEkQkxWJkVAAV3VMmmmGdEX5EHbqIYF0fuWYHPvKrz4X7fryuYcuR0ows9Ohw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<!-- Leaflet Coverage -->
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.1/leaflet.css">
<link rel="stylesheet" type="text/css" href="https://unpkg.com/leaflet-coverage@0.7/leaflet-coverage.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.1/leaflet.js"></script>
<script src="https://unpkg.com/covutils@0.6/covutils.min.js"></script>
<script src="https://unpkg.com/leaflet-coverage@0.7/leaflet-coverage.min.js"></script>
</head>
<body>
<a id="dataExport">
<button id="exportButton" onclick="exportData()">Export</button>
</a>
<label id="importLabel" for="dataImport">Import</label>
<input id="dataImport" type="file" name="dataImport" onchange="importData()"/>
<div class='map' id="map"></div>
</body>
<script src="index.js"></script>
</html>
JS
const baseLayer = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'});
const bounds = [[48, -12,], [61.5, 3]];
const map = L.map('map', {
layers: [baseLayer],
maxBounds: bounds,
maxBoundsViscosity: 0.9,
}).setView([((bounds[1][0] + bounds[0][0]) / 2), ((bounds[1][1] + bounds[0][1]) / 2)], 5);
const controlLayers = L.control.layers({"OSM": baseLayer}, undefined, {collapsed: false}).addTo(map);
const dataArray = [];
loadCoverageData(mockData); // Mocking a fetch and response
function loadCoverageData(data) {
console.log("Attempting to load: \n", data);
dataArray.push(data) // User could have multiple layers of
CovJSON.read(data)
.then((coverage) => {
let dataLayer = C.dataLayer(coverage, {parameter: Object.keys(data.parameters)[0]})
.on('afterAdd', () => {
if (dataLayer.palette) {
C.legend(dataLayer).addTo(map)
}
if (dataLayer.timeSlices) {
new C.TimeAxis(dataLayer).addTo(map)
}
})
controlLayers.addOverlay(dataLayer, Object.keys(data.parameters)[0]);
});
}
function replacer(key, value) {
if (value instanceof Map) {
return {
dataType: 'Map',
value: Array.from(value.entries()),
};
} else {
return value;
}
}
function reviver(key, value) {
if (typeof value === 'object' && value !== null) {
if (value.dataType === 'Map') {
return new Map(value.value);
}
}
return value;
}
function exportData() {
let encodedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(dataArray, replacer));
document.getElementById('dataExport').setAttribute('href', 'data:' + encodedData);
document.getElementById('dataExport').setAttribute('download', 'drawing-data.json');
}
function importData() {
let dataFile = document.getElementById('dataImport').files[0]
let reader = new FileReader();
reader.onload = function (event) {
let data = JSON.parse(event.target.result, reviver);
data.forEach((coverageSet) => {
loadCoverageData(coverageSet);
})
}
reader.readAsText(dataFile);
}
const mockData = {
"type": "Coverage",
"domain": {
"type": "Domain",
"domainType": "MultiPolygon",
"axes": {
"composite": {
"dataType": "polygon",
"coordinates": [
"x",
"y"
],
"values": [
[
[
[
9.92,
54.98
],
[
9.93,
54.59
],
[
13.64,
54.07
],
[
15.01,
51.10
],
[
12.24,
50.26
],
[
12.52,
49.54
],
[
13.59,
48.87
],
[
12.88,
48.28
],
[
13.02,
47.63
],
[
9.59,
47.52
],
[
8.52,
47.83
],
[
7.46,
47.62
],
[
8.09,
49.01
],
[
6.18,
49.46
],
[
5.98,
51.85
],
[
6.84,
52.22
],
[
7.10,
53.69
],
[
8.80,
54.02
],
[
8.52,
54.96
],
[
9.92,
54.98
]
]
],
[
[
[
-3.00,
58.63
],
[
-1.95,
57.68
],
[
-2.08,
55.90
],
[
0.46,
52.92
],
[
1.68,
52.73
],
[
0.55,
50.76
],
[
-3.61,
50.22
],
[
-5.26,
51.99
],
[
-3.63,
54.61
],
[
-5.58,
55.31
],
[
-6.14,
56.78
],
[
-5.00,
58.63
],
[
-3.00,
58.63
]
]
]
]
},
"t": {
"values": [
"2015"
]
}
},
"referencing": [
{
"coordinates": [
"x",
"y"
],
"system": {
"type": "GeographicCRS",
"id": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
}
},
{
"coordinates": [
"t"
],
"system": {
"type": "TemporalRS",
"calendar": "Gregorian"
}
}
]
},
"parameters": {
"TEMP": {
"type": "Parameter",
"unit": {
"label": {
"en": "Degree Celsius"
},
"symbol": {
"value": "Cel",
"type": "http://www.opengis.net/def/uom/UCUM/"
}
},
"observedProperty": {
"label": {
"en": "Average air temperature"
}
}
}
},
"ranges": {
"TEMP": {
"type": "NdArray",
"dataType": "float",
"axisNames": [
"composite"
],
"shape": [
2
],
"values": [
22.8,
15.1
]
}
}
}
CS
.map {
height: 80vh;
width: 80vw;
}
由于在 loadCoverageData
中的 CovJSON.read(data)
中使用了 data
,因此 javascript 引用仍然存在并且被动态覆盖/修改:
function loadCoverageData(data) {
console.log("Attempting to load: \n", data);
dataArray.push(data) // User could have multiple layers of
CovJSON.read(data).then((coverage) => {
简单地“复制”数据对象并中断引用。一种解决方案是使用 data = JSON.parse(JSON.stringify(data))
:
function loadCoverageData(data) {
console.log("Attempting to load: \n", data);
dataArray.push(data) // User could have multiple layers of
data = JSON.parse(JSON.stringify(data))
CovJSON.read(data).then((coverage) => {