百度地图 JavaScript API(WebGL 版)在 Web 可视化中的表现力远超普通 2D 版本,支持三维倾斜摄影、海量点渲染、个性化样式等高级能力。本文基于实际项目,总结 “在 Vue3 + TypeScript 项目中优雅集成百度地图 WebGL” 的核心步骤与坑点,帮助你快速完成业务需求。
1. 准备工作
步骤 | 要点 |
---|---|
申请 AK | 登陆百度地图开放平台 → 创建应用 → 获取 AK(浏览器端 JSAPI)。 |
配置白名单 | 将 本地调试域名 / 生产域名 添加到 IP/URL 白名单,否则控制台报 AK does not exist or has not been added to whitelist 。 |
个性化样式 | 在控制台「自定义地图」生成 StyleID,更换主题色或隐藏 POI。 |
2. 动态加载脚本
传统 <script>
写死在 index.html
会阻塞首屏;推荐在组件内按需加载,并利用 callback 避免多次加载。
const BAIDU_AK = '你的AK'
const CALLBACK = '你的样式id'
function loadBaiduScript(): Promise<void> {
return new Promise((resolve, reject) => {
if (window.BMapGL) return resolve() // 已加载
// 多个组件并发调用时,挂队列
if ((window as any)[CALLBACK]) {
(window as any)[CALLBACK + 'Queue'] = (window as any)[CALLBACK + 'Queue'] || []
;(window as any)[CALLBACK + 'Queue'].push(resolve)
return
}
;(window as any)[CALLBACK] = () => {
resolve()
const q = (window as any)[CALLBACK + 'Queue'] || []
q.forEach((fn: () => void) => fn())
}
const script = document.createElement('script')
script.src = `https://api.map.baidu.com/api?v=1.0&type=webgl&ak=${BAIDU_AK}&callback=${CALLBACK}`
script.onerror = () => reject(new Error('百度地图脚本加载失败'))
document.head.appendChild(script)
})
}
Tips:别忘了在
onBeforeUnmount
里将 Map 实例设为null
,以便下一次重新创建。
3. 初始化地图
let map: any = null
const STYLE_ID = '你的StyleID'
function initMap(containerId = 'map') {
map = new window.BMapGL.Map(containerId)
// ❶ 设置中心点/缩放级别
const center = new window.BMapGL.Point(116.404, 39.915) // 经度, 纬度
map.centerAndZoom(center, 11)
// ❷ 交互与控件
map.enableScrollWheelZoom() // 滚轮缩放
map.addControl(new window.BMapGL.ZoomControl())
map.addControl(new window.BMapGL.ScaleControl())
// ❸ 个性化样式
map.setMapStyleV2({ styleId: STYLE_ID })
}
坑点速览
症状 | 原因与解决 |
---|---|
地图一直是灰色网格 | ① AK/白名单错误;② 未开启 WebGL 加速(需 HTTPS domain)。 |
坐标颠倒 | 百度 API 使用 Point(lng, lat)(先经度后纬度),与高德相反。 |
控件无法拖动 | 忘记 enableScrollWheelZoom() 或误盖全屏遮罩层。 |
4. 添加自定义标记
import pinImg from '@/assets/icons/pin.png'
function addMarker(point: window.BMapGL.Point, title = '') {
const size = new window.BMapGL.Size(32, 32)
const icon = new window.BMapGL.Icon(pinImg, size, { anchor: new window.BMapGL.Size(16, 16) })
const marker = new window.BMapGL.Marker(point, { icon })
title && marker.setTitle(title)
map.addOverlay(marker)
return marker
}
信息窗口
marker.addEventListener('click', () => {
const info = new window.BMapGL.InfoWindow(`<div>${title}</div>`, { width: 200 })
map.openInfoWindow(info, point)
})
性能:海量点请优先考虑官方 点聚合 或 海量点 解决方案,或使用第三方
bmapgl-marker-clusterer
。
5. 缩放级别联动:汇总气泡 vs 详情标记
const markers: any[] = []
let summaryMarker: any = null
let detailZoom = 12 // (初始化层级 + 1)
function updateVisibility() {
const showDetail = map.getZoom() >= detailZoom
markers.forEach(m => showDetail ? m.show() : m.hide())
if (showDetail && summaryMarker) summaryMarker.hide()
else if (!showDetail) summaryMarker?.show()
}
map.addEventListener('zoomend', updateVisibility)
function createSummaryLabel(centerPoint: window.BMapGL.Point, total = markers.length) {
const label = new window.BMapGL.Label(total.toString(), { position: centerPoint })
label.setStyles({
width: '48px', height: '48px', lineHeight: '44px',
borderRadius: '50%', background: 'rgba(7,38,53,.5)', color: '#fff', textAlign: 'center'
})
map.addOverlay(label)
return label
}
- WebGL API 无
setVisible
—— 请用show()
/hide()
。 - 阈值动态计算 ——
detailZoom = map.getZoom() + 1
保证进入页面先展示汇总。
6. TypeScript 类型补充
declare global {
interface Window {
BMapGL: any
}
}
也可
npm i -D @types/bmapgl
获取社区维护的 d.ts,但 WebGL 版接口不完全一致,需适当as any
。
7. 性能优化建议
- 懒加载脚本 —— 只在需要地图的路由加载 SDK;切换后销毁。
- 资源托管 —— 将自定义图片上传 CDN,替换本地引用可加速。
- 重复创建 —— 判断
window.BMapGL
已存在即复用,无需二次注入<script>
。 - 防抖缩放事件 ——
zoomend
触发频次较低已可满足;如果监听zooming
建议加lodash.throttle
。
8. 集成常见报错速查表
报错信息 | 解决方案 |
---|---|
BMapGL is undefined | SDK 未加载成功;确认 AK、callback 拼写、脚本 URL 是否被拦截。 |
baiduMapInitCallback is not a function | 组件销毁—重新加载时全局回调已被覆盖;在脚本注入逻辑中做队列分发。 |
Net::ERR_BLOCKED_BY_CLIENT | 浏览器插件(AdBlock 等)拦截,切换无痕或白名单域名。 |
地图白屏不报错 | 混用 2D + WebGL API;检查是否调用 new BMap.Point 而非 BMapGL.Point 。 |
9. 结语
整合百度地图 WebGL 到 Vue3 并不复杂,但需要注意:
- 动态脚本加载 + 队列回调,解决并发与重复注册问题;
- 经纬度顺序、show/hide API 差异,尤其是在从高德迁移时;
- 缩放阈值、汇总气泡 等交互逻辑,提前规划体验;
- AK 白名单、HTTPS、WebGL 支持,排查首屏灰网格。
掌握以上要点,你就能在任何 Vue3 项目中快速集成一张性能优、交互佳的百度地图。希望本文对你有所帮助,欢迎点赞收藏,一起探索更酷的地理可视化玩法!