向 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: '&copy; <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) => {