Maplibre GL JS:预加载隐藏地图的画布尺寸动画实现问题
解决MapLibre GL地图全屏平滑尺寸动画的方案
方案1:CSS Transform缩放(推荐,性能最优)
核心思路是让地图提前渲染到目标尺寸,通过CSS transform实现视觉上的缩放动画,避免地图频繁重绘:
- 初始化时,将地图容器设置为全屏尺寸(
width: 100vw; height: 100vh),但用transform: scale(0.1)(或对应小尺寸的缩放比例)配合transform-origin: top left,同时设置overflow: hidden、visibility: visible(不要用display: none,否则地图无法初始化)。 - 切换全屏时,添加CSS过渡动画:
transition: transform 0.5s ease,将transform改为scale(1)。 - 动画结束后(监听
transitionend事件),移除transform样式,确保容器尺寸正常,再调用一次map.resize()做最终校准(可选,因为地图已经是全屏尺寸)。
代码示例:
#map-container { width: 100vw; height: 100vh; transform: scale(0.1); transform-origin: top left; transition: transform 0.5s ease; overflow: hidden; } #map-container.fullscreen { transform: scale(1); }
const mapContainer = document.getElementById('map-container'); // 初始化地图(容器已设为全屏尺寸,只是缩放隐藏) const map = new maplibregl.Map({ container: 'map-container', style: 'your-style-url', center: [lng, lat], zoom: 10 }); // 触发全屏动画 function triggerFullscreen() { mapContainer.classList.add('fullscreen'); // 动画结束后校准 mapContainer.addEventListener('transitionend', () => { mapContainer.style.transform = ''; map.resize(); }, { once: true }); }
方案2:逐帧动画配合map.resize()
如果必须通过修改容器宽高实现动画,可以在动画的每一帧同步调用map.resize(),但需注意性能优化:
- 用
requestAnimationFrame驱动动画,逐帧计算容器当前宽高并设置。 - 动画前降低地图渲染模式,减少重绘开销,动画结束后恢复。
代码示例:
const mapContainer = document.getElementById('map-container'); const targetWidth = window.innerWidth; const targetHeight = window.innerHeight; const startWidth = mapContainer.offsetWidth; const startHeight = mapContainer.offsetHeight; const duration = 500; // 动画时长,单位ms let startTime; // 降低渲染性能以提升动画流畅度 map.setRenderMode('low'); function animate(timestamp) { if (!startTime) startTime = timestamp; const elapsed = timestamp - startTime; const progress = Math.min(elapsed / duration, 1); // 计算当前尺寸 const currentW = startWidth + (targetWidth - startWidth) * progress; const currentH = startHeight + (targetHeight - startHeight) * progress; // 更新容器尺寸 mapContainer.style.width = `${currentW}px`; mapContainer.style.height = `${currentH}px`; // 同步调整地图 map.resize(); if (progress < 1) { requestAnimationFrame(animate); } else { // 动画结束,恢复渲染性能 map.setRenderMode('high'); } } // 启动动画 requestAnimationFrame(animate);
注意事项
- 避免用
display: none隐藏初始地图:这会导致地图无法获取容器尺寸,初始化异常。改用visibility: hidden、opacity: 0或transform缩放隐藏。 - 方案1的性能远优于方案2,因为transform是GPU加速,不会触发频繁的地图重绘,推荐优先使用。
内容的提问来源于stack exchange,提问作者Kalle
相关产品推荐
相关产品推荐

