更新记录
1.0.0(2026-08-17) 下载此版本
- 实现Android、iOS和HarmonyOS的统一地图API开发
- 支持地图展示、覆盖物展示以及其它常用功能
平台兼容性
uni-app x(4.85)
| Chrome | Safari | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 鸿蒙插件版本 | 微信小程序 |
|---|---|---|---|---|---|---|---|---|
| - | - | 7.0 | 1.0.0 | 12 | 1.0.0 | 17 | 1.0.0 | - |
baidumap-view
百度地图 UTS 插件
基于百度地图 SDK 的
uni-app x原生地图插件,支持 Android、iOS、HarmonyOS 三端统一 API,覆盖地图展示、状态控制、覆盖物、富文本气泡与地图事件。
支持平台
| 平台 | 支持状态 |
|---|---|
| Android | ✅ |
| iOS | ✅ |
| HarmonyOS | ✅ |
插件能力
- 地图展示:中心点、缩放、旋转、俯视角、最小/最大缩放级别
- 手势控制:缩放、拖动、旋转、俯视手势开关
- 图层控制:POI、室内图、室内 POI、路况、比例尺、指南针、缩放控件
- 地图类型:标准地图、卫星地图、坐标类型切换、个性化样式
- 视野控制:fitBounds、地图状态获取、可视区域获取、屏幕坐标与经纬度互转
- 地理工具:坐标转换、距离计算、点在多边形/矩形判断
- 覆盖物:
Marker、Polyline、Polygon、Circle、Label - 富文本气泡:
Marker和Label支持RichView - POI 检索:城市内检索、周边检索、地理编码、逆地理编码、SUG 联想
- 路线规划:步行、骑行、驾车路线规划
- 地图事件:点击、双击、长按、POI 点击、覆盖物点击、地图状态变化、地图加载/渲染完成
- 调试能力:插件内部日志开关
版本要求
HBuilderX:^4.85uni-app-x:^4.85
快速开始
1. 引入插件
import {
SdkInit,
LogUtil,
createNativeMapContext,
INativeMapContext,
LatLng,
MapOverlay,
MapPoi,
Marker,
Polyline,
Polygon,
Circle,
Label,
RichView,
RichViewItem
} from '@/uni_modules/baidumap-view'
2. 初始化隐私与 AK
使用地图前必须先同意隐私政策并配置百度地图 AK。
SdkInit.setAgreePrivacy(true)
SdkInit.setAK('你的百度地图AK')
3. 页面中放置地图组件
id 必填,且同一页面内必须唯一。
<baidumap-view
id="demoMap"
style="width: 750rpx; height: 900rpx"
:lat="39.914779"
:lng="116.404"
:zoom="13"
@onMapLoadFinish="onMapLoadFinish"
@onMapClick="onMapClick"
@onMapOverlayClick="onMapOverlayClick"
/>
4. 地图加载完成后创建上下文
let map : INativeMapContext | null = null
function onMapLoadFinish() {
map = createNativeMapContext('demoMap', getCurrentInstance()?.proxy ?? null)
}
onBeforeUnmount(() => {
map?.destroy()
})
完整页面示例
<template>
<view>
<button @click="addMarker">添加标记</button>
<button @click="moveCenter">移动中心点</button>
<baidumap-view
id="demoMap"
style="width: 750rpx; height: 900rpx"
:lat="39.914779"
:lng="116.404"
:zoom="13"
:showTrafficMap="true"
@onMapLoadFinish="onMapLoadFinish"
@onMapClick="onMapClick"
@onMapPoiClick="onMapPoiClick"
@onMapOverlayClick="onMapOverlayClick"
/>
</view>
</template>
<script setup lang="uts">
import {
SdkInit,
createNativeMapContext,
INativeMapContext,
LatLng,
MapOverlay,
MapPoi,
Marker,
LogUtil
} from '@/uni_modules/baidumap-view'
SdkInit.setAgreePrivacy(true)
SdkInit.setAK('你的百度地图AK')
LogUtil.setMapLogStatus(true)
let map : INativeMapContext | null = null
let marker : Marker | null = null
function onMapLoadFinish() {
map = createNativeMapContext('demoMap', getCurrentInstance()?.proxy ?? null)
}
function addMarker() {
if (map == null) {
return
}
marker?.remove()
const newMarker = new Marker()
const position : LatLng = { lat: 39.92235, lng: 116.380338 }
newMarker.setPosition(position)
newMarker.icon = '/static/icon_marker.png'
newMarker.addToMap('demoMap')
marker = newMarker
}
function moveCenter() {
const center : LatLng = { lat: 39.915, lng: 116.404 }
map?.setCenter(center.lat, center.lng)
map?.setZoom(15)
}
function onMapClick(position : LatLng) {
console.log('map click', position)
}
function onMapPoiClick(poi : MapPoi) {
console.log('poi click', poi.name, poi.uid)
}
function onMapOverlayClick(overlay : MapOverlay) {
const currentMarker = marker
if (currentMarker != null && currentMarker.getId() == overlay.id) {
currentMarker.updateIcon('/static/icon_marker_selected.png')
}
}
onBeforeUnmount(() => {
marker?.remove()
map?.destroy()
})
</script>
组件属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
id |
string |
必填 | 地图唯一标识 |
lat |
number |
39.914779 |
初始中心纬度 |
lng |
number |
116.404000 |
初始中心经度 |
zoom |
number |
18 |
初始缩放级别 |
minZoom |
number |
3 |
最小缩放级别 |
maxZoom |
number |
23 |
最大缩放级别 |
rotate |
number |
0 |
地图旋转角度 |
overlook |
number |
0 |
地图俯视角 |
showMapPoi |
boolean |
true |
是否展示 POI |
showMapIndoorPoi |
boolean |
true |
是否展示室内 POI |
showBaseIndoorMap |
boolean |
true |
是否展示室内图 |
showTrafficMap |
boolean |
true |
是否展示路况图层 |
zoomGesturesEnabled |
boolean |
true |
是否启用缩放手势 |
moveGesturesEnabled |
boolean |
true |
是否启用拖动手势 |
rotateGesturesEnabled |
boolean |
true |
是否启用旋转手势 |
overlookingGesturesEnabled |
boolean |
true |
是否启用俯视手势 |
组件事件
| 事件名 | 参数 | 说明 |
|---|---|---|
@onMapLoadFinish |
- | 地图加载完成 |
@onMapRenderFinish |
- | 地图渲染完成 |
@onMapClick |
LatLng |
点击地图空白区域 |
@onMapDoubleClick |
LatLng |
双击地图 |
@onMapLongPress |
LatLng |
长按地图 |
@onMapPoiClick |
MapPoi |
点击地图 POI |
@onMapOverlayClick |
MapOverlay |
点击覆盖物或富文本子项 |
@onMapStatusChangeStart |
number |
地图状态开始变化 |
@onMapStatusChange |
- | 地图状态变化中 |
@onMapStatusChangeFinish |
- | 地图状态变化结束 |
事件数据结构
type LatLng = {
lat : number,
lng : number
}
type MapPoi = {
name : string,
uid : string,
position : LatLng
}
type MapOverlay = {
id : number,
type : 'marker' | 'polyline' | 'polygon' | 'circle' | 'label' | 'multipoint',
isItemView ?: boolean,
itemIndex ?: number
}
地图控制 API
通过 createNativeMapContext 获取 INativeMapContext 后可调用以下能力:
地图状态
map?.setZoom(15)
map?.setMinZoom(5)
map?.setMaxZoom(20)
map?.setRotate(30)
map?.setOverlook(20)
map?.setCenter(39.915, 116.404)
map?.setMapStatus({
center: { lat: 39.915, lng: 116.404 },
zoom: 14,
rotate: 0,
overlook: 0,
minZoom: 3,
maxZoom: 23,
isAnimate: true,
animationTime: 300
})
手势开关
map?.zoomGesturesEnabled(true)
map?.moveGesturesEnabled(true)
map?.rotateGesturesEnabled(true)
map?.overlookingGesturesEnabled(true)
图层与控件
map?.showMapPoi(true)
map?.showMapIndoorPoi(true)
map?.showBaseIndoorMap(true)
map?.showTrafficMap(true)
map?.showScaleControl(true)
map?.showZoomControls(true)
map?.showCompass(true)
生命周期
if (map?.isValid() == true) {
console.log('map context valid')
}
map?.destroy()
地图类型与坐标系
// 地图类型:1-标准地图 2-卫星地图
map?.setMapType(1)
// 坐标类型:1-BD09LL(百度) 2-GCJ02(国测局)
map?.setCoordType(1)
// 地图样式:0-标准 1-深色
map?.setMapStyleMode(0)
// 个性化样式(本地文件)
map?.setCustomMapStylePath('/static/custom_style.sty')
// 个性化样式(样式ID,从百度地图开放平台获取)
map?.setCustomMapStyleById('your_style_id')
视野控制
// 调整视野以包含指定坐标点
const bounds : LatLng[] = [
{ lat: 39.915, lng: 116.404 },
{ lat: 39.925, lng: 116.414 }
]
const fitOptions : FitBoundsOptions = {
padding: 50,
isAnimate: true,
animationTime: 300
}
map?.fitBounds(bounds, fitOptions)
// 获取当前地图状态
map?.getMapStatus((status : MapStatus) => {
console.log('center:', status.center, 'zoom:', status.zoom)
})
// 获取可视区域
map?.getVisibleRegion((region : VisibleRegion) => {
console.log('northeast:', region.northeast, 'southwest:', region.southwest)
})
// 屏幕坐标与经纬度互转
map?.screenToLatLng(200, 300, (latlng : LatLng) => {
console.log('screen to latlng:', latlng)
})
map?.latLngToScreen({ lat: 39.915, lng: 116.404 }, (point : ScreenPoint) => {
console.log('latlng to screen:', point.x, point.y)
})
覆盖物使用
建议所有覆盖物变量声明为
let xxx : Type | null = null,并在重复添加前先调用remove(),避免地图上累积旧对象。
Marker
let marker : Marker | null = null
function addMarker() {
marker?.remove()
const newMarker = new Marker()
const position : LatLng = { lat: 39.92235, lng: 116.380338 }
newMarker.setPosition(position)
newMarker.icon = '/static/icon_marker.png'
newMarker.addToMap('demoMap')
marker = newMarker
}
marker?.updatePosition({ lat: 39.915, lng: 116.404 })
marker?.updateIcon('/static/icon_marker_selected.png')
marker?.remove()
Polyline
let polyline : Polyline | null = null
function addPolyline() {
polyline?.remove()
const newPolyline = new Polyline()
newPolyline.setPoints([
{ lat: 39.915, lng: 116.404 },
{ lat: 39.925, lng: 116.414 },
{ lat: 39.935, lng: 116.424 }
])
newPolyline.color = '#1E80FF'
newPolyline.width = 8
newPolyline.addToMap('demoMap')
polyline = newPolyline
}
polyline?.updatePoints([
{ lat: 39.915, lng: 116.404 },
{ lat: 39.945, lng: 116.434 }
])
polyline?.updateColor('#FF5A5F')
polyline?.updateWidth(10)
Polygon
let polygon : Polygon | null = null
function addPolygon() {
polygon?.remove()
const newPolygon = new Polygon()
newPolygon.setPointsData([
{ lat: 39.915, lng: 116.404 },
{ lat: 39.925, lng: 116.434 },
{ lat: 39.905, lng: 116.444 }
])
newPolygon.borderWidth = 4
newPolygon.borderColor = '#1E80FF'
newPolygon.fillColor = '#4D1E80FF'
newPolygon.addToMap('demoMap')
polygon = newPolygon
}
polygon?.updatePoints([
{ lat: 39.915, lng: 116.404 },
{ lat: 39.935, lng: 116.424 },
{ lat: 39.905, lng: 116.444 }
])
polygon?.updateBorderWidth(6)
polygon?.updateBorderColor('#FF5A5F')
polygon?.updateFillColor('#4DFF5A5F')
Circle
let circle : Circle | null = null
function addCircle() {
circle?.remove()
const newCircle = new Circle()
newCircle.setCenter({ lat: 39.915, lng: 116.404 })
newCircle.radius = 500
newCircle.borderWidth = 4
newCircle.borderColor = '#1E80FF'
newCircle.fillColor = '#4D1E80FF'
newCircle.addToMap('demoMap')
circle = newCircle
}
circle?.updateCenter({ lat: 39.918, lng: 116.408 })
circle?.updateRadius(800)
circle?.updateBorderWidth(6)
circle?.updateBorderColor('#FF5A5F')
circle?.updateFillColor('#4DFF5A5F')
Label
let label : Label | null = null
function addLabel() {
label?.remove()
const newLabel = new Label()
newLabel.setPosition({ lat: 39.915, lng: 116.404 })
newLabel.text = '百度地图'
newLabel.fontSize = 28
newLabel.fontColor = '#1F2329'
newLabel.borderWidth = 2
newLabel.borderColor = '#FFFFFF'
newLabel.rotate = 0
newLabel.addToMap('demoMap')
label = newLabel
}
label?.updateText('地图插件')
label?.updateFontSize(32)
label?.updateFontColor('#1E80FF')
label?.updateBorderWidth(3)
label?.updateBorderColor('#FF5A5F')
label?.updateRotate(10)
label?.updatePosition({ lat: 39.918, lng: 116.408 })
RichView 富文本气泡
Marker 和 Label 支持 addRichView() / removeRichView(),可用于实现信息气泡、组合图文标注等场景。
RichView 类型
type RichViewItem = {
type : string,
text ?: string,
fontSize ?: number,
fontColor ?: string,
fontBold ?: boolean,
borderWidth ?: number,
borderColor ?: string,
maxLines ?: number,
image ?: string,
direction ?: 'vertical' | 'horizontal',
children ?: Array<RichViewItem>,
width ?: number,
height ?: number,
background ?: string,
backgroundColor ?: string,
margin ?: {
top ?: number,
left ?: number,
bottom ?: number,
right ?: number
},
gravity ?: 'left' | 'center' | 'right',
clickable ?: boolean
}
type RichView = {
items : Array<RichViewItem>,
direction ?: 'vertical' | 'horizontal',
locate ?: 'top' | 'bottom' | 'left' | 'right',
offsetX ?: number,
offsetY ?: number,
gravity ?: 'left' | 'center' | 'right',
background ?: string,
backgroundColor ?: string,
collisionPriority ?: number
}
给 Marker 添加气泡
const richView : RichView = {
locate: 'top',
offsetY: -12,
direction: 'vertical',
items: [
{
type: 'layout',
direction: 'horizontal',
children: [
{
type: 'image',
image: '/static/avatar.png',
width: 48,
height: 48,
margin: { right: 8 }
},
{
type: 'text',
text: '教学点位',
fontSize: 26,
fontColor: '#1F2329',
fontBold: true,
clickable: true
}
]
}
]
}
marker?.addRichView(richView)
marker?.removeRichView()
点击 RichView 子项时,@onMapOverlayClick 的 MapOverlay 会携带:
isItemViewitemIndex
可据此判断是否点击了气泡内某个元素。
检索服务
通过 map?.getSearchService() 获取检索服务实例。
POI 检索
const searchService = map?.getSearchService()
// 城市内检索
searchService?.poiCitySearch({
keyword: '餐厅',
city: '北京',
pageIndex: 0,
pageSize: 10
}, (result) => {
result.poiList?.forEach((poi) => {
console.log(poi.name, poi.address, poi.location)
})
})
// 周边检索
searchService?.poiNearbySearch({
keyword: '酒店',
location: { lat: 39.915, lng: 116.404 },
radius: 1000,
pageIndex: 0,
pageSize: 10
}, (result) => {
result.poiList?.forEach((poi) => {
console.log(poi.name, poi.distance)
})
})
地理编码
// 地址 -> 坐标
searchService?.geoCode({
address: '北京市海淀区上地十街10号',
city: '北京'
}, (result) => {
console.log('location:', result.location)
})
// 坐标 -> 地址
searchService?.reverseGeoCode({
location: { lat: 39.915, lng: 116.404 }
}, (result) => {
console.log('address:', result.address)
console.log('poiList:', result.poiList)
})
SUG 联想检索
searchService?.suggestionSearch({
keyword: '天安门',
city: '北京'
}, (result) => {
result.suggestionList?.forEach((item) => {
console.log(item.key, item.address, item.location)
})
})
路线规划
步行路线
searchService?.walkingRouteSearch({
startLocation: { lat: 39.915, lng: 116.404 },
endLocation: { lat: 39.925, lng: 116.414 }
}, (result) => {
const route = result.routeLines?.[0]
if (route != null) {
console.log('distance:', route.distance, 'duration:', route.duration)
// route.steps 包含路线各步骤
// route.wayPoints 包含路线点串,可用于绑定 Polyline
}
})
骑行路线
searchService?.ridingRouteSearch({
startLocation: { lat: 39.915, lng: 116.404 },
endLocation: { lat: 39.925, lng: 116.414 }
}, (result) => {
const route = result.routeLines?.[0]
if (route != null) {
console.log('distance:', route.distance, 'duration:', route.duration)
}
})
驾车路线
searchService?.drivingRouteSearch({
startLocation: { lat: 39.915, lng: 116.404 },
endLocation: { lat: 39.935, lng: 116.434 }
}, (result) => {
const route = result.routeLines?.[0]
if (route != null) {
console.log('distance:', route.distance, 'duration:', route.duration)
// route.trafficInfo 包含路况信息
}
})
路线绘制示例
let routePolyline : Polyline | null = null
function drawRoute(wayPoints : LatLng[]) {
routePolyline?.remove()
const polyline = new Polyline()
polyline.setPoints(wayPoints)
polyline.color = '#1E80FF'
polyline.width = 8
polyline.addToMap('demoMap')
routePolyline = polyline
// 调整视野以显示完整路线
map?.fitBounds(wayPoints, { padding: 80, isAnimate: true })
}
地理工具
const geoUtils = map?.getGeoUtils()
// 坐标转换
const gcj02 = geoUtils?.bd09llToGcj02({ lat: 39.915, lng: 116.404 })
const bd09ll = geoUtils?.gcj02ToBd09ll({ lat: 39.91, lng: 116.40 })
// 计算两点距离(米)
const distance = geoUtils?.getDistance(
{ lat: 39.915, lng: 116.404 },
{ lat: 39.925, lng: 116.414 }
)
// 判断点是否在多边形内
const polygon : LatLng[] = [
{ lat: 39.91, lng: 116.40 },
{ lat: 39.92, lng: 116.41 },
{ lat: 39.91, lng: 116.42 }
]
const inPolygon = geoUtils?.isPointInPolygon({ lat: 39.915, lng: 116.405 }, polygon)
// 判断点是否在矩形范围内
const inBounds = geoUtils?.isPointInBounds(
{ lat: 39.915, lng: 116.405 },
{ lat: 39.91, lng: 116.40 }, // southwest
{ lat: 39.92, lng: 116.42 } // northeast
)
推荐使用规范
1. 使用局部常量创建覆盖物
为避免 UTS 对可变变量的 Smart Cast 限制,推荐使用局部常量模式:
let marker : Marker | null = null
function addMarker() {
marker?.remove()
const newMarker = new Marker()
newMarker.setPosition({ lat: 39.92235, lng: 116.380338 })
newMarker.icon = '/static/icon_marker.png'
newMarker.addToMap('demoMap')
marker = newMarker
}
2. 覆盖物点击时先取局部引用
function onMapOverlayClick(overlay : MapOverlay) {
const currentMarker = marker
if (currentMarker != null && currentMarker.getId() == overlay.id) {
currentMarker.updateIcon('/static/icon_marker_selected.png')
}
}
3. 注意资源路径
- 图片资源建议使用项目内绝对静态路径,如
'/static/icon_marker.png' Marker.icon、RichView.image、RichView.background会在原生层转换为绝对路径
4. 页面卸载时释放资源
onBeforeUnmount(() => {
marker?.remove()
map?.destroy()
})
调试日志
LogUtil.setMapLogStatus(true)
console.log(LogUtil.getMapLogStatus())
常见问题
1. 地图不显示
请检查:
- 是否已调用
SdkInit.setAgreePrivacy(true) - 是否已正确设置
SdkInit.setAK(...) - 地图组件是否设置了明确宽高
id是否唯一
2. createNativeMapContext 返回空
请检查:
- 是否在
@onMapLoadFinish之后再创建上下文 createNativeMapContext('地图id', getCurrentInstance()?.proxy ?? null)中的id是否与组件一致
3. 覆盖物添加失败
请检查:
- 是否先创建了地图上下文
LatLng坐标是否合法Marker.icon或 RichView 图片资源路径是否有效addToMap('xxx')的参数是否与地图id一致

收藏人数:
下载插件并导入HBuilderX
赞赏(0)
下载 4
赞赏 0
下载 12512567
赞赏 1943
赞赏
京公网安备:11010802035340号