OpenLayers:切换TileImage源URL时保留WebGL瓦片显示的方法
解决方案:保留旧瓦片直至新瓦片加载完成
直接调用TileImage.setUrl()会清空现有瓦片缓存并触发重新加载,导致旧瓦片立即消失。要实现新瓦片加载完成前保留旧瓦片,最简便的方式是通过双图层交替预加载的方式实现:
核心思路
维护两个WebGLTile图层:一个作为当前显示的气象图层,另一个作为预加载图层(初始隐藏)。切换时间戳时,先让预加载图层加载新瓦片,待其完成加载并可渲染后,再切换两个图层的可见性,确保视图始终有瓦片显示。
修改后的代码
import Map from 'ol/Map.js'; import OSM from 'ol/source/OSM.js'; import TileLayer from 'ol/layer/WebGLTile.js'; import View from 'ol/View.js'; import TileImage from 'ol/source/TileImage.js'; let urlA = "https://www.example.com/temperature.php?tile_x={x}&tile_y={y}&tile_zoom={z}&datetime=now"; let urlB = "https://www.example.com/temperature.php?tile_x={x}&tile_y={y}&tile_zoom={z}&datetime=now+1hour"; let urlC = "https://www.example.com/temperature.php?tile_x={x}&tile_y={y}&tile_zoom={z}&datetime=now+2hours"; // 当前显示的气象图层 let currentLayer = new TileLayer({ source: new TileImage({url: urlA}), }); // 预加载图层,初始隐藏 let preloadLayer = new TileLayer({ source: new TileImage(), visible: false, }); const map = new Map({ target: 'map', layers: [ new TileLayer({ source: new OSM(), }), currentLayer, preloadLayer, ], view: new View({ center: [0, 0], zoom: 0, }), }); // 切换瓦片逻辑 function switchWeatherTile(targetUrl) { // 给预加载图层设置新URL preloadLayer.getSource().setUrl(targetUrl); // 监听预加载图层的首次渲染事件(说明瓦片已加载完成) const renderHandler = () => { // 切换图层可见性 currentLayer.setVisible(false); preloadLayer.setVisible(true); // 交换图层引用,为下一次切换做准备 [currentLayer, preloadLayer] = [preloadLayer, currentLayer]; // 移除监听,避免重复触发 preloadLayer.un('render', renderHandler); }; preloadLayer.once('render', renderHandler); } // 绑定按钮事件 document.getElementById("tempA").addEventListener("click", e => { switchWeatherTile(urlA); e.preventDefault(); }) document.getElementById("tempB").addEventListener("click", e => { switchWeatherTile(urlB); e.preventDefault(); }) document.getElementById("tempC").addEventListener("click", e => { switchWeatherTile(urlC); e.preventDefault(); })
补充说明
- 利用
render事件判断瓦片加载完成:当预加载图层能触发render事件时,说明已有足够的瓦片可以渲染到视图中,此时切换不会出现空白。 - 如果需要更精确地等待所有可见瓦片加载完成,可以监听数据源的
tileloadend事件,统计已加载瓦片数量与当前视图所需瓦片数量,匹配后再切换图层,但render事件已能满足绝大多数场景的需求。
内容的提问来源于stack exchange,提问作者Kuba Maroušek
相关产品推荐
相关产品推荐

