地图 loading 不能只靠 window.load,因为百度地图 SDK 异步加载时 BMap 对象挂载晚于 load 事件,导致隐藏 loading 后出现 200–500ms 白屏;正确做法是通过 callback 参数(如 &callback=initMap)确保 BMap 可用后再隐藏 loading。

地图加载前必须显示 loading,否则用户会看到空白容器或错位布局;最稳做法是把 #loading 元素写死在 开头,并用 window.addEventListener('load', ...) 隐藏它——但百度地图这类异步 SDK 不能只靠 load 事件,得等 BMap 构造完成才真正可用。
为什么地图 loading 不能只靠 window.load
浏览器的 window.load 确保图片、CSS、字体等资源就绪,但百度地图 JS 是动态加载的(尤其是异步方式),BMap 对象可能在 window.load 之后几毫秒甚至几百毫秒才挂载到全局。此时若已隐藏 loading,用户会看到地图容器空白 200–500ms。
- 同步加载时,
BMap在脚本执行完就可用,但脚本本身阻塞页面,window.load延迟严重 - 异步加载时,
BMap依赖 callback 回调,window.load完全无法感知其状态 - 常见错误:在
<script src="http://api.map.baidu.com/api?v=3.0&ak=xxx"></script>后立刻 newBMap.Map—— 此时BMap还未定义,报ReferenceError: BMap is not defined
百度地图异步加载 + loading 的正确时机控制
异步加载是推荐方式,不阻塞页面,但必须用 callback 参数指定初始化函数,loading 的隐藏必须嵌套其中。
- 在
或开头放好<div id="loading"></div>,用内联样式确保首帧渲染 -
src地址末尾加上&callback=initMap,例如:http://api.map.baidu.com/api?v=3.0&ak=xxx&callback=initMap - 定义全局
initMap函数,在里面创建地图、隐藏 loading,并处理可能的失败兜底 - 不要在
initMap外部调用new BMap.Map,否则仍会报未定义
<body>
<div id="loading" style="position:fixed;top:0;left:0;width:100%;height:100%;background:#fff;z-index:9999;display:flex;justify-content:center;align-items:center;">
<div class="spinner"></div>
</div>
<div id="map" style="width:100%;height:400px;"></div>
<script>
function initMap() {
try {
const map = new BMap.Map("map");
map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
document.getElementById('loading').style.display = 'none';
} catch (e) {
console.error('BMap init failed:', e);
document.getElementById('loading').style.display = 'none';
}
}
</script>
<script src="http://api.map.baidu.com/api?v=3.0&ak=YOUR_AK&callback=initMap"></script>
</body>
同步加载时如何避免 loading 卡住
同步加载虽简单,但脚本阻塞会导致 window.load 滞后,且 loading 若过早隐藏,地图容器还没渲染出来;若过晚,则白屏太久。
立即学习“前端免费学习笔记(深入)”;
- 把
<script src="..."></script>放在底部,而非 - 用
document.body.onload或window.addEventListener('load', ...)隐藏 loading,而不是DOMContentLoaded - 务必加超时兜底:比如 8 秒后强制隐藏 loading,防止 AK 错误、网络中断导致无限等待
- 地图容器
<div id="map"> 必须在 script 标签之前存在,否则 <code>new BMap.Map("map")找不到节点loading 元素容易被忽略的三个细节
即使逻辑写对,视觉和交互上仍常出问题:遮不住、闪一下、点不了。
-
z-index必须大于地图容器和其他绝对定位元素,建议设为9999起,避免被第三方 UI 库覆盖 - 移动端需加
pointer-events: none到 loading 容器上,否则点击穿透会误触底下的地图控件 - 动画用
transform: rotate()+border-radius: 50%,别用will-change: transform,旧 iPad 上反而掉帧
-



















