问题描述
给定一些 ESRI Vector Tile 服务,我想告诉 OpenLayers 如何处理来自 VectorTileSource 的 tile 错误。具体来说,我想告诉 OpenLayers,当一个 tile 无法通过网络加载时,OpenLayers 应该使用“这个其他”的 tile 来代替,并拉伸它。
我的应用程序有一些“魔法”来确定新磁贴的 tileCoord 值。
function _magic(tile,url) { /* returns tileCoordLike like [z,x,y] from tilecoord.js
createOrUpdate*/}
function _request(tile,url) { /* returns Promise */}
// https://openlayers.org/en/latest/apidoc/module-ol_Tile.html#~LoadFunction
function tileLoadFunction(tile,url) {
_request(tile,url).then(
function () { /*success*/ console.log('it worked,great')},function () { /*error*/
let tileCoordLike = _magic(tile);
console.log("Need to use a different tile instead:");
console.log(tileCoordLike);
tile.setState(ol.TileState.ERROR);
})
})
类似的问题询问了如何告诉 OpenLayers 使用静态图像,但我实际上希望 OL 使用不同的图块。有没有办法做到这一点?
解决方法
在 IndexedDB 中存储图块时我有类似的要求,但它也应该适用于替代网址。
请注意,矢量切片的切片加载函数比图像切片的加载函数更复杂,因为它必须为切片设置加载函数,请参见 https://openlayers.org/en/latest/apidoc/module-ol_source_VectorTile-VectorTile.html
中的示例首先创建一个函数来获取一个 url 并将结果作为对象 url 返回,或者如果失败则返回一个替代 url
function altFetch(url1,url2) {
fetch(url1).then(function(response) {
if (response.ok) {
return response.blob();
}
}).then(function(result) {
if (result) {
resolve(URL.createObjectURL(result));
} else {
resolve(url2);
}
});
}
然后在加载函数中(使用 https://github.com/openlayers/openlayers/blob/main/src/ol/featureloader.js#L60 中的默认加载器),您应该撤销占用内存的对象 url
function(tile,url) {
tile.setLoader(function(extent,resolution,projection) {
altFetch(url,magic(tile,url)).then(function(result) {
let onLoad;
if (result.indexOf('blob:') == 0) {
onLoad = function() {
tile.onLoad.bind(tile).apply(null,arguments);
URL.revokeObjectURL(result);
}
} else {
onLoad = tile.onLoad.bind(tile);
}
loadFeaturesXhr(
result,tile.getFormat(),extent,projection,onLoad,tile.onError.bind(tile)
);
});
});
}