L.CRS.Simple 传单最低缩放级别仍然太高

Leaflet lowest zoom level is still too high with L.CRS.Simple

试图检索区域的一部分,但由于某种原因无法看到整个区域,即使缩放级别为 0,(据说)我们应该看到整个世界。 我正在使用 L.CRS.Simple 因为它使用 EPSG:3763 并且在 CRS 列表中看不到那个。我正在检索 JSON 中的数据,因为在绑定 geoJSON 时,无法将 3D 坐标数据转换为 2D 平面数据。

    const queryRegionText = "where=OBJECTID > 0"
    const geoJsonURL2 = "https://sig.cm-figfoz.pt/arcgis/rest/services/Internet/MunisigWeb_DadosContexto/MapServer/2/query?f=json&returnGeometry=true&geometryType=esriGeometryPolyline&spatialRel=esriSpatialRelIntersects&outFields=*&outSR=3763&" + queryRegionText

    var map = L.map('mapid', {
      crs: L.CRS.Simple
    }).setView([-58216.458338, 42768.347232], 0);


    L.control.scale({ metric: true }).addTo(map);

    fetch(geoJsonURL2).then(function (response) {
      response.json().then(function (data) {
        data.features.forEach(element => {
          if (element.geometry.rings) {
            element.geometry.rings.forEach(point => {
              L.polyline(point, { color: 'red' }).addTo(map);
            })
          }
        });
      });
    });

    var popup = L.popup();

    function onMapClick(e) {
      popup
        .setLatLng(e.latlng)
        .setContent("You clicked the map at " + e.latlng.toString())
        .openOn(map);
    }

    map.on('click', onMapClick);
<html>

<head>
  <title>Leaflet - testing</title>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
  <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
</head>

<body>
  <div id="mapid" style="width: 600px; height: 400px;"></div>
</body>
</html>

TL;DR: 创建地图时,将最小缩放比例设置为零以下。这应该有效:

var map = L.map('mapid', {
  crs: L.CRS.Simple, minZoom: -6
}).setView([-57728, 55296], -6);

说明

通常,Leaflet 从 latitude/longitude 坐标系转换为屏幕像素,假设世界在缩放级别 0 时为 256 像素高。在每个更高的缩放级别,像素数量加倍(解释得很好在 Zoom levels tutorial) 中。有了这个假设,地图的选项默认为 {minZoom: 0, maxZoom: Infinity}(因为您没有添加任何将这些值设置为任何不同的图层)。

当您使用 L.CRS.Simple 时,在缩放级别 0 时,它会将 1 个坐标单位映射到 1 个屏幕像素。您的数据看起来大约有 18000 个坐标单位高,因此它不适合您的 400 像素高的地图。为了使其适合,我们需要每个屏幕像素映射到大约 45 个坐标单位。 2^5 是 32,2^6 是 64,所以我们需要缩小 5 到 6 倍。幸运的是,Leaflet 接受负缩放级别,因此将缩放设置为 -6 就可以了。但要使其正常工作,您需要设置 {minZoom: -6},这样地图就不会卡在缩放级别 0。Non-geographical Maps tutorial.

中有一个很好的示例

使用 L.CRS.Simple 应该适合您,只要近似值认为每个纬度单位与每个经度单位(正方形世界)的长度相同。由于这在现实世界中通常不是真的,因此使用简单投影会导致一些失真。如果失真对于您感兴趣的功能很重要,那么您将需要按照@IvanSanchez 的建议,使用 L.CRSProj4Leaflet 来查找如何正确使用 EPSG:3763。

所以,在阅读了 proj4leaflet 之后,提出了这段代码。提前感谢以上评论和回复。

const queryRegionText = "where=OBJECTID > 0"
const geoJsonURL2 = "https://sig.cm-figfoz.pt/arcgis/rest/services/Internet/MunisigWeb_DadosContexto/MapServer/2/query?f=geojson&returnGeometry=true&geometryType=esriGeometryPolyline&spatialRel=esriSpatialRelIntersects&outFields=*&outSR=3763&" + queryRegionText

const map = L.map('map', {
  center: [40.14791, -8.87009],
  zoom: 13
});

proj4.defs("EPSG:3763", "+proj=tmerc +lat_0=39.66825833333333 +lon_0=-8.133108333333334 +k=1 +x_0=0 +y_0=0 +ellps=GRS80 +units=m +no_defs");

fetch(geoJsonURL2).then(function (response) {
  response.json().then(function (data) {
    L.Proj.geoJson(data).addTo(map);
  });
});

var popup = L.popup();

function onMapClick(e) {
  popup
    .setLatLng(e.latlng)
    .setContent("You clicked the map at " + e.latlng.toString())
    .openOn(map);
}

map.on('click', onMapClick);
<head>
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
  <link rel="stylesheet" href="main.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.4/proj4.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4leaflet/1.0.2/proj4leaflet.js"></script>
</head>

<body class="">
  <div id="map" style="width: 600px; height: 400px;"></div>
  </div>
  <script src="main.js"></script>
</body>