繁体   English   中英

确保所有图块都加载到 Open Layers 3 XYZ 源中

[英]Ensuring all tiles are loaded in Open Layers 3 XYZ source

我们有一些层使用ol.source.XYZ源。 对于加载策略,我们使用ol.loadingstrategy.tile(new ol.tilegrid.createXYZ({})) 在进行其他操作之前,我们需要确保所有图块都已完全加载到地图视图中。

我们遇到了多篇关于此的文章,但尚未找到 100% 的解决方案,这将为我们提供所需的解决方案。 即使情况并非如此,逻辑也会返回 true。 我们已经尝试使用示例页面上显示的 tileloadstart、tileloadend、tileloaderror 事件,但这似乎并不总是返回预期的结果。

此处的 GIS Stack Exchange 文章似乎很有前景,因为我们可以将下面列出的代码与 tileloadstart/tileloadend 事件结合使用,但有许多函数调用仅在ol-debug.js 中可用,而在ol.js源代码中不可用. 因此,下面粘贴的代码不适用于ol.js 此代码只是引用的 GIS Stack Exchange 文章的副本。

function calculateNumberOfTiles(tileSource) {
     var tg = (tileSource.getTileGrid()) ? tileSource.getTileGrid(): ol.tilegrid.getForProjection(map.getView().getProjection()), 
            z = tg.getZForResolution(map.getView().getResolution()),
            tileRange = tg.getTileRangeForExtentAndZ(map.getView().calculateExtent(map.getSize()), z),
            xTiles = tileRange['maxX'] - tileRange['minX'] + 1,
            yTiles = tileRange['maxY'] - tileRange['minY'] + 1;
        return xTiles * yTiles;
}

我有两个问题,任何人都可以就我们可能遗漏的内容提供任何其他想法吗? 谢谢你的帮助。

  1. 当函数调用挂在tilegrid对象的原型上时,为什么它们在 ol-debug.js 而不是 ol.js 中可用
  2. 任何其他建议如何告诉所有图块已完全加载到地图中?

加载事件

您假设源上的每个tileloadstart事件都应跟随相应图块的tileloadendtileloaderror是正确的。 可以使用链接的官方示例来跟踪加载图块的数量。

当发射的总和tileloadendtileloaderror事件等于数量tileloadstart事件,没有加载正在进行中。 如果不是这种情况,您应该尝试制作一个可重现的示例,因为它可能是库中的一个错误。

然而,了解这些事件的含义很重要。 tileloadend事件并不表示该图块在地图上可见,而是表示该图块已完成加载并可用于渲染。 tile 的实际渲染将在调用事件处理程序后完成。 因此,任何需要有关何时加载和渲染所有图块的信息的图块加载逻辑(例如在截取屏幕截图/创建打印时)都必须等到下一个postrender事件。

你提到了tileloadend和实际出现在地图上的 tile 之间的 5-10 秒,这对于渲染相关来说太长了(除非你做了一些非常奇怪的渲染回调)。

ol-debug.js 与 ol.js

与许多 JS 库一样,OpenLayers 代码在构建过程中经过优化和最小化,以创建更小、更高效的构建。 任何不属于 API 的类型或函数都将被缩小或删除。 只应使用ol.js 中可用并记录在openlayers.org上的方法,因为任何缩小的方法都可能会更改每个构建。

ol-debug.js 是该库的非优化版本,用于调试或探索。

这是我的方法。 它使用未记录的 API,但它适用于非调试 openlayers 4.2.0。

//"Dirty" tiles can be in one of two states: Either they are being downloaded,
//or the map is holding off downloading their replacement, and they are "wanted."
//We can tell when the map is ready when there are no tiles in either of these
//states, and rendering is done.

var numInFlightTiles = 0;
map.getLayers().forEach(function (layer) {
    var source = layer.getSource();
    if (source instanceof ol.source.TileImage) {
        source.on('tileloadstart', function () {++numInFlightTiles})
        source.on('tileloadend', function () {--numInFlightTiles})
    }
})

map.on('postrender', function (evt) {
    if (!evt.frameState)
        return;

    var numHeldTiles = 0;
    var wanted = evt.frameState.wantedTiles;
    for (var layer in wanted)
        if (wanted.hasOwnProperty(layer))
            numHeldTiles += Object.keys(wanted[layer]).length;

    var ready = numInFlightTiles === 0 && numHeldTiles === 0;
    if (map.get('ready') !== ready)
        map.set('ready', ready);
});

map.set('ready', false);

function whenMapIsReady(callback) {
    if (map.get('ready'))
        callback();
    else
        map.once('change:ready', whenMapIsReady.bind(null, callback));
}

此答案已过时,并且不适用于 openlayers 6 或更高版本。

如此处所述: https : //github.com/openlayers/openlayers/releases/tag/v6.0.0

对此的解决方案是将后渲染放在这样的图层上

const mapLayer = map.getLayers().getArray()[0];

mapLayer.on('postrender', (evt) => {});

这将在渲染第一层后触发后渲染

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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