0
votes

The recommended approach for translating a vector tile layer seems to be to translate the canvas context on precompose (see OpenLayers 3: per-layer translation for tiled image layers). As noted, only those tiles that fall within the map’s pre-translation visible extent are rendered.

How can I achieve the effect of translation without losing those boundary tiles?

I also tried using a custom tile grid with an origin (https://github.com/openlayers/openlayers/issues/9514) but this appears to be a misuse of the ‘origin’ parameter so tiles were only partially drawn. I am guessing that custom origins are required to fall on a tile boundary; mine do not.

Update: Mike’s solution is correct. As I recall, I had tried Mike’s approach before submitting this question and, although the layer was translated, there was a problem with portions of tiles disappearing (or being drawn in the wrong location). But experimenting with Mike’s example, I noticed that setting useInterimTilesOnError to false in my application fixed both the disappearing and misdrawn tile issue. Perhaps there is some problem with the tiles I am using, but it is interesting that when the layer is not offset, tiles are rendered properly regardless of how useInterimTilesOnError is set.

1
One example is translating by pixels on the canvas (same number of pixels regardless of resolution), in the other you attempt to move the origin (same distance on the ground regardless of resolution). Which effect did you want?Mike
@Mike The latter. But as I can readily convert between pixels and coordinates, the first example would work for me so long as the required tiles were not missing.tweedlebee

1 Answers

0
votes

It seems to be sufficient to offset the extent of the tilegrid (the origin will default to the top left of the extent).

var proj3857 = ol.proj.get('EPSG:3857');

var raster = 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 map = new ol.Map({
  layers: [raster],
  target: document.getElementById('map'),
  view: new ol.View({
      center: ol.proj.fromLonLat([0, 50]),
      maxZoom: 23,
      zoom: 5,
      projection: proj3857
  })
});

var dx = -200000;
var dy = -100000;

var extent = proj3857.getExtent();
offsetExtent = [extent[0] + dx, extent[1] + dy, extent[2] + dx, extent[3] + dy];

var layer = new ol.layer.VectorTile({
  source: new ol.source.VectorTile({
    format: new ol.format.MVT(),
    url: 'https://basemaps.arcgis.com/v1/arcgis/rest/services/World_Basemap/VectorTileServer/tile/{z}/{y}/{x}.pbf',
    tileGrid: ol.tilegrid.createXYZ({ extent: offsetExtent, maxZoom: 18 })
  }),
  //useInterimTilesOnError: false,
  style: new ol.style.Style({
    stroke: new ol.style.Stroke({
      width: 1,
      color: 'white'
    })
  })
});

map.addLayer(layer);
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet"/>
<div id="map" class="map"></div>

Console log from the OpenLayers example near Japan enter image description here