简体   繁体   中英

How to create custom tiles that fit on a certain extent OpenLayers5

I want to create a custom tile that is a perfect fit on a certain extent. For example, I want to be able to map it on the map at exact spots of an Open Source Map. I saw this example, but it does not explain how the tiles are made and how to make it such that it fits the extent perfectly. The example below puts custom layer at an extent, I want to know how to create such tiles. I am using XYZ source for my code. Example was taken from :

https://openlayers.org/en/latest/examples/arcgis-tiled.html

<!DOCTYPE html>
<html>
  <head>
    <title>Tiled ArcGIS MapServer</title>
    <link rel="stylesheet" href="https://openlayers.org/en/v5.3.0/css/ol.css" type="text/css">
    <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>

  </head>
  <body>
    <div id="map" class="map"></div>
    <script>
      import Map from 'ol/Map.js';
      import View from 'ol/View.js';
      import TileLayer from 'ol/layer/Tile.js';
      import {OSM, TileArcGISRest} from 'ol/source.js';

      var url = 'https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/' +
          'Specialty/ESRI_StateCityHighway_USA/MapServer';

      var layers = [
        new TileLayer({
          source: new OSM()
        }),
        new TileLayer({
          extent: [-13884991, 2870341, -7455066, 6338219],
          source: new TileArcGISRest({
            url: url
          })
        })
      ];
      var map = new Map({
        layers: layers,
        target: 'map',
        view: new View({
          center: [-10997148, 4569099],
          zoom: 4
        })
      });
    </script>
  </body>
</html>

In that example the tiles use a standard EPSG:3857 grid, the same as the OSM layer. The extent has been set to limit requests to a specific area (USA including Hawaii and most of Alaska - but not the western end of the Aleutians). At zoom level zero the single tile covers the world (transparent shows as black):

在此处输入图片说明

If you set the same extent on the OSM layer you would also restrict the area displayed, but it wouldn't affect the tiles. With global projections it is normal to stick to a standard grid and restrict the layer extent to avoid requests to areas where you don't have tiles. In other projections you can create you own grid, and specify that in OpenLayers using the source's tileGrid option to match what you created.

Here's an example of how to set up a custom tile grid for https://server.arcgisonline.com/ArcGIS/rest/services/Polar/Antarctic_Imagery/MapServer

 // define polar projection proj4.defs("EPSG:3031", "+proj=stere +lat_0=-90 +lat_ts=-71 +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs"); ol.proj.proj4.register(proj4); // redefine transforms to catch errors var inverse = ol.proj.getTransform('EPSG:3031', 'EPSG:3857'); var forward = ol.proj.getTransform('EPSG:3857', 'EPSG:3031'); ol.proj.addCoordinateTransforms( 'EPSG:3857', 'EPSG:3031', function(coordinate) { try { return forward(coordinate) } catch (e) { return [undefined, undefined] } }, function(coordinate) { try { return inverse(coordinate) } catch (e) { return [undefined, undefined] } } ); var baseMapLayer = new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', maxZoom: 23 }) }); var extent = [-3.369955099203E7, -3.369955099203E7, 3.369955099203E7, 3.369955099203E7]; var maxResolution = 238810.81335399998; var resolutions = []; for (var i = 0; i < 24; i++) { resolutions[i] = maxResolution / Math.pow(2, i); } var esriArctic = new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'https://services.arcgisonline.com/arcgis/rest/services/Polar/Antarctic_Imagery/MapServer/tile/{z}/{y}/{x}', projection: 'EPSG:3031', tileGrid: new ol.tilegrid.TileGrid({ extent: extent, resolutions: resolutions }) }) }); // create a "layer spy" around the pole esriArctic.on('precompose', function(event) { radius = 4000000 / event.frameState.viewState.resolution; var ctx = event.context; var pixelRatio = event.frameState.pixelRatio; ctx.save(); ctx.beginPath(); position = map.getPixelFromCoordinate(ol.proj.fromLonLat([0, -90], 'EPSG:3031')); // only show a circle around the position ctx.arc(position[0] * pixelRatio, position[1] * pixelRatio, radius * pixelRatio, 0, 2 * Math.PI); ctx.clip(); }); // after rendering the layer, restore the canvas context esriArctic.on('postcompose', function(event) { var ctx = event.context; ctx.restore(); }); var map = new ol.Map({ target: 'map', layers: [baseMapLayer, esriArctic], view: new ol.View({ projection: 'EPSG:3031', center: ol.proj.fromLonLat([0, -80], 'EPSG:3031'), zoom: 3 }) }); 
  html, body, #map { width: 100%; height: 100%; overflow: hidden; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script> <link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet"/> <script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script> <body> <div id="map" class="map"></div> </body> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM