有没有办法告诉 OpenLayers 在 TILEERROR 上使用不同的 Tile?

Posted

技术标签:

【中文标题】有没有办法告诉 OpenLayers 在 TILEERROR 上使用不同的 Tile?【英文标题】:Is there a way to tell OpenLayers to use a Different Tile on TILEERROR? 【发布时间】:2021-08-27 19:36:40 【问题描述】:

鉴于一些 ESRI Vector Tile 服务,我想告诉 OpenLayers 如何处理来自 VectorTileSource 的图块错误。具体来说,我想告诉 OpenLayers,当一个 tile 无法通过网络加载时,OpenLayers 应该使用“this other” 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 使用不同的图块。有没有办法做到这一点?

【问题讨论】:

【参考方案1】:

在 IndexedDB 中存储图块时,我也有类似的要求,但它也应该适用于替代 url。

请注意,矢量瓦片的瓦片加载函数比图像瓦片的瓦片加载函数更复杂,因为它必须为瓦片设置加载器函数,请参阅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,
                resolution,
                projection,
                onLoad,
                tile.onError.bind(tile)
            );
        );
    );

【讨论】:

以上是关于有没有办法告诉 OpenLayers 在 TILEERROR 上使用不同的 Tile?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Bing Maps Quadkeys 作为 Openlayers 3 Tile 源

OpenLayers工作原理

在 OpenLayers 3 tileloadstart 事件中停止加载图块

02openlayers 控件

openlayers6 mapserver加载地图底图

Openlayers 3 热力图