С useInterimTilesOnError: true
, похоже, возникает проблема, потому что экстент проекции вида не соответствует экстенту сетки листов, и плитки обрезаются на основе проекции вида.Векторные листы нельзя перепроецировать, поэтому причина в одинаковой проекции, но разной степени.Определение переведенного экстента и использование его для вида, по-видимому, исправляет его, и растровый слой можно «перепроецировать» (хотя, поскольку единственные различия между координатами будут близки к линии даты, маловероятно, что потребуется слишком много служебных данных).
Я добавил еще несколько сценариев к вашей демонстрации:
var proj3857 = ol.proj.get('EPSG:3857');
proj4.defs('EPSG:3857X', '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs');
if (ol.proj.proj4 && ol.proj.proj4.register) { ol.proj.proj4.register(proj4); }
var dx = 20000;
var dy = 0;
var extent = ol.proj.get('EPSG:3857').getExtent();
var offsetExtent = [extent[0] + dx, extent[1] + dy, extent[2] + dx, extent[3] + dy];
var proj3857X = ol.proj.get('EPSG:3857X');
proj3857X.setGlobal(true);
proj3857X.setExtent(offsetExtent);
var center = ol.proj.fromLonLat([133.9789237, -23.6188074]);
var view = new ol.View({
center: center,
maxZoom: 23,
zoom: 10,
projection: proj3857
});
var viewX = new ol.View({
center: center,
maxZoom: 23,
zoom: 10,
projection: proj3857X
});
var sync = true;
view.on(['change:center','change:resolution','change:rotation'], function() {
if (sync) {
var center = view.getCenter();
var zoom = view.getZoom();
var rotation = view.getRotation();
sync = false;
viewX.animate({
center: center,
zoom: zoom,
rotation: rotation,
duration: 0
}, function() { sync = true; });
}
});
viewX.on(['change:center','change:resolution','change:rotation'], function() {
if (sync) {
var center = viewX.getCenter();
var zoom = viewX.getZoom();
var rotation = viewX.getRotation();
sync = false;
view.animate({
center: center,
zoom: zoom,
rotation: rotation,
duration: 0
}, function() { sync = true; });
}
});
var raster = new ol.layer.Tile({
opacity: .4,
source: new ol.source.XYZ({
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
maxZoom: 23,
})
});
createMap('untranslated-false', 0, 0, false, view);
createMap('untranslated-true', 0, 0, true, view);
createMap('false', dx, dy, false, view);
createMap('true', dx, dy, true, view);
createMap('projected-false', dx, dy, false, viewX);
createMap('projected-true', dx, dy, true, viewX);
function createMap(id, dx, dy, useInterimTilesOnError, view) {
var map = new ol.Map({
layers: [raster],
target: id,
view: view
});
var extent = proj3857.getExtent();
var 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(),
//wrapX: false,
projection: view.getProjection(),
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: useInterimTilesOnError,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
width: 1,
color: 'black'
})
})
});
map.addLayer(layer);
map.addLayer(new ol.layer.Tile({
source: new ol.source.TileDebug({
projection: proj3857,
tileGrid: ol.tilegrid.createXYZ({
extent: offsetExtent,
maxZoom: 18
})
})
}));
}
.map {
height: 400px;
width: 100%;
margin-bottom: 10px;
}
<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>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div>
<h4>Untranslated plus useInterimTilesOnError: false</h4>
<div id="untranslated-false" class="map"></div>
</div>
<div>
<h4>Untranslated plus useInterimTilesOnError: true</h4>
<div id="untranslated-true" class="map"></div>
</div>
<div>
<h4>Translated plus useInterimTilesOnError: false</h4>
<div id="false" class="map"></div>
</div>
<div>
<h4>Translated plus useInterimTilesOnError: true</h4>
<div id="true" class="map"></div>
</div>
<div>
<h4>Projected plus useInterimTilesOnError: false</h4>
<div id="projected-false" class="map"></div>
</div>
<div>
<h4>Projected plus useInterimTilesOnError: true</h4>
<div id="projected-true" class="map"></div>
</div>