OpenLayers - TileArcGISRest 与 XYZ

发布于 2025-01-12 21:02:28 字数 2163 浏览 3 评论 0原文

TileArcGISRest 上的 OpenLayers 文档 说:
对于缓存的 ArcGIS 服务,使用 ol/source/XYZ 可以获得更好的性能。

但是 XYZ 不适合 ArcGis,并且我的 ArcGis 切片地图(使用单融合地图缓存)在使用时不适合 OSM XYZ(参见屏幕截图)。我的代码中只有 TileArcGISRest 使地图图层适合 OSM 图层。这给我留下了一些问题:

  1. 如何将 TileArcGISRest 迁移到 XYZ?
  2. 为什么 XYZ 表现更好?
  3. 为什么 TileArcGISRest 没有相应地实现性能改进?

我的代码如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css"
      type="text/css"
    />
    <style>
      .map {
        height: 95vh;
        width: 100%;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script>
    <title>OpenLayers example</title>
  </head>
  <body>
    <div id="map" class="map"></div>
    <script type="text/javascript">
      const host = "map_host";

      const map = new ol.Map({
        target: "map",
        layers: [
          // OpenStreetMap layer
          new ol.layer.Tile({
            source: new ol.source.OSM(),
          }),

          new ol.layer.Tile({
            source: new ol.source.TileArcGISRest({
              url: `https://${host}/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBilder/MapServer`,
            }),
          }),

          new ol.layer.Tile({
            source: new ol.source.XYZ({
              url: `https://${host}/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBilder/MapServer/tile/{z}/{y}/{x}`,
            }),
          }),
        ],
        view: new ol.View({
          center: [0, 6000000],
          zoom: 3,
        }),
      });
    </script>
  </body>
</html>

TileArcGISRest 与 XYZ

OpenLayers docs on TileArcGISRest says:
For cached ArcGIS services, better performance is available by using ol/source/XYZ instead.

But XYZ is not adapted to ArcGis and my ArcGis tile map (with Single Fused Map Cache) does not fit OSM when using XYZ (see screenshot). Only TileArcGISRest in my code makes the map layer fit the OSM layer. That leaves me with some questions:

  1. How do I migrate TileArcGISRest to XYZ?
  2. Why does XYZ perform better?
  3. Why doesn't TileArcGISRest implement performance improvements accordingly?

My code is as follows:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css"
      type="text/css"
    />
    <style>
      .map {
        height: 95vh;
        width: 100%;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script>
    <title>OpenLayers example</title>
  </head>
  <body>
    <div id="map" class="map"></div>
    <script type="text/javascript">
      const host = "map_host";

      const map = new ol.Map({
        target: "map",
        layers: [
          // OpenStreetMap layer
          new ol.layer.Tile({
            source: new ol.source.OSM(),
          }),

          new ol.layer.Tile({
            source: new ol.source.TileArcGISRest({
              url: `https://${host}/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBilder/MapServer`,
            }),
          }),

          new ol.layer.Tile({
            source: new ol.source.XYZ({
              url: `https://${host}/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBilder/MapServer/tile/{z}/{y}/{x}`,
            }),
          }),
        ],
        view: new ol.View({
          center: [0, 6000000],
          zoom: 3,
        }),
      });
    </script>
  </body>
</html>

TileArcGISRest vs. XYZ

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你爱我像她 2025-01-19 21:02:28

如果您从缓存图块的服务 json 中获取图块网格,您可以为图块指定正确的 OpenLayers XYZ 源。由于源位于 UTM 投影中(OpenLayers 需要 proj4),您必须将其重新投影到与 OSM 相同的 Web Mercator,或者指定 UTM33 作为视图投影并重新投影 OSM 背景。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css"
      type="text/css"
    />
    <style>
      .map {
        height: 95vh;
        width: 100%;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.5/proj4.js"></script>
    <title>OpenLayers example</title>
  </head>
  <body>
    <div id="map" class="map"></div>
    <script type="text/javascript">

      proj4.defs("EPSG:25833","+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");
      ol.proj.proj4.register(proj4);

      const map = new ol.Map({
        target: "map",
        layers: [
          // OpenStreetMap layer
          new ol.layer.Tile({
            source: new ol.source.OSM(),
          }),
        ],
        view: new ol.View({
          center: [0, 9000000],
          zoom: 3,
         }),
      });

      const host = "services.geodataonline.no";
      fetch(
        `https://${host}/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBilder/MapServer?f=json`
      ).then(function(response) {
         return response.json();
      }).then(function(serviceJson) {
        const extent = [
          serviceJson.fullExtent.xmin,
          serviceJson.fullExtent.ymin,
          serviceJson.fullExtent.xmax,
          serviceJson.fullExtent.ymax,
        ];
        const origin = [
          serviceJson.tileInfo.origin.x,
          serviceJson.tileInfo.origin.y,
        ];
        const resolutions = serviceJson.tileInfo.lods.map(function(l) { return l.resolution; });
        const tileSize = [serviceJson.tileInfo.cols, serviceJson.tileInfo.rows];
        const wkid = serviceJson.tileInfo.spatialReference.latestWkid;
        const tileGrid = new ol.tilegrid.TileGrid({
           extent: extent,
           origin: origin,
           resolutions: resolutions,
           tileSize: tileSize,
        });
        map.addLayer(
          new ol.layer.Tile({
            source: new ol.source.XYZ({
              url: `https://${host}/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBilder/MapServer/tile/{z}/{y}/{x}`,
              tileGrid: tileGrid,
              projection: 'EPSG:' + wkid,
            }),
          })
        );
      })

    </script>
  </body>
</html>

If you obtain the tilegrid from the service json for the cached tiles you can specify the correct OpenLayers XYZ source for the tiles. As the source is in a UTM projection (for which OpenLayers needs proj4) you must either reproject it to web mercator the same as OSM, or specify UTM33 as the view projection and reproject the OSM background.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/css/ol.css"
      type="text/css"
    />
    <style>
      .map {
        height: 95vh;
        width: 100%;
      }
    </style>
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.13.0/build/ol.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.5/proj4.js"></script>
    <title>OpenLayers example</title>
  </head>
  <body>
    <div id="map" class="map"></div>
    <script type="text/javascript">

      proj4.defs("EPSG:25833","+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");
      ol.proj.proj4.register(proj4);

      const map = new ol.Map({
        target: "map",
        layers: [
          // OpenStreetMap layer
          new ol.layer.Tile({
            source: new ol.source.OSM(),
          }),
        ],
        view: new ol.View({
          center: [0, 9000000],
          zoom: 3,
         }),
      });

      const host = "services.geodataonline.no";
      fetch(
        `https://${host}/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBilder/MapServer?f=json`
      ).then(function(response) {
         return response.json();
      }).then(function(serviceJson) {
        const extent = [
          serviceJson.fullExtent.xmin,
          serviceJson.fullExtent.ymin,
          serviceJson.fullExtent.xmax,
          serviceJson.fullExtent.ymax,
        ];
        const origin = [
          serviceJson.tileInfo.origin.x,
          serviceJson.tileInfo.origin.y,
        ];
        const resolutions = serviceJson.tileInfo.lods.map(function(l) { return l.resolution; });
        const tileSize = [serviceJson.tileInfo.cols, serviceJson.tileInfo.rows];
        const wkid = serviceJson.tileInfo.spatialReference.latestWkid;
        const tileGrid = new ol.tilegrid.TileGrid({
           extent: extent,
           origin: origin,
           resolutions: resolutions,
           tileSize: tileSize,
        });
        map.addLayer(
          new ol.layer.Tile({
            source: new ol.source.XYZ({
              url: `https://${host}/arcgis/rest/services/Geocache_UTM33_EUREF89/GeocacheBilder/MapServer/tile/{z}/{y}/{x}`,
              tileGrid: tileGrid,
              projection: 'EPSG:' + wkid,
            }),
          })
        );
      })

    </script>
  </body>
</html>

活泼老夫 2025-01-19 21:02:28

迈克的答案是正确的,您必须指定正确的tilegrid才能使用ol.source.XYZ。

但我会回答你的两个问题:

为什么 XYZ 表现更好?

使用 ol.source.XYZ 可以直接访问图块,图块已经生成并存储在图块服务器上的某个位置。服务器无需处理。它只是发回图块,因此请求速度更快。
请求 XYZ 请求的示例:

https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/8/90/45

为什么 TileArcGISRest 没有相应地实现性能改进?

使用 TileArcGISRest 源。图块是使用您提供的参数(投影、bbox、宽度、高度...)动态创建的。因此与 XYZ 相比,需要更多的后端处理。
请求示例:

https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer/export?
F=image
&FORMAT=PNG32
&TRANSPARENT=true
&SIZE=256%2C256
&BBOX=-13149614.849955441%2C4383204.9499851465%2C-12523442.714243278%2C5009377.08569731
&BBOXSR=3857
&IMAGESR=3857
&DPI=90

总而言之,XYZ 使用缓存切片,而 TileArcGISRest 动态生成切片。

The answer of Mike is correct you have to specify the correct tilegrid to use an ol.source.XYZ.

But I will answers to your 2 questions:

Why does XYZ perform better?

Using an ol.source.XYZ you access the tiles directly, tiles are already generated and stored somewhere on your tile server. No treatment needed by the server. It just send back the tile so requests are faster.
Example of a request XYZ request:

https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/8/90/45

Why doesn't TileArcGISRest implement performance improvements accordingly?

Using a TileArcGISRest source. Tiles are created on the fly with the parameter you give (projection, bbox, wisth,height ..). So more backend treatment are needed compared to XYZ.
Example of a request :

https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer/export?
F=image
&FORMAT=PNG32
&TRANSPARENT=true
&SIZE=256%2C256
&BBOX=-13149614.849955441%2C4383204.9499851465%2C-12523442.714243278%2C5009377.08569731
&BBOXSR=3857
&IMAGESR=3857
&DPI=90

To summarize, XYZ use cached tile and TileArcGISRest generates tiles on the fly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文