【HarmonyOS实战】 MapKit地图接入:从初始化到显示完整地图
"附近加油站"的核心功能是地图,地图来自华为MapKit。MapKit 是华为提供的地图能力套件,类似高德地图 SDK 或 Google Maps SDK,但深度集成在 HarmonyOS 里。这篇文章从头讲 MapKit 的接入流程,把里地图相关的代码全部讲清楚。项目预览声明变量mapOptionscallback配置 mapOptions:设置初始位置、缩放级别、地图类型定义 callback
文章目录
前言
"附近加油站"的核心功能是地图,地图来自华为 MapKit。MapKit 是华为提供的地图能力套件,类似高德地图 SDK 或 Google Maps SDK,但深度集成在 HarmonyOS 里。
这篇文章从头讲 MapKit 的接入流程,把 GasStationPage.ets 里地图相关的代码全部讲清楚。
项目预览


一、MapKit 的核心类
使用 MapKit 需要了解三个核心对象:
| 对象 | 作用 |
|---|---|
MapComponent |
地图 UI 组件,嵌入到 build() 里显示地图 |
mapCommon.MapOptions |
地图初始化配置(中心点、缩放级别、地图类型等) |
map.MapComponentController |
地图控制器,控制地图行为(移动、添加标记、监听事件) |
三者的关系:
MapOptions(配置参数)
↓ 传给
MapComponent(UI显示)
↓ 通过 callback 返回
MapComponentController(控制器)
↓ 用于
添加标记、移动镜头、监听点击...
二、声明相关变量
// GasStationPage.ets
@Component
struct GasStationPage {
private mapOptions?: mapCommon.MapOptions; // 地图配置(可选,初始为空)
private mapController?: map.MapComponentController; // 地图控制器(回调里赋值)
private callback?: AsyncCallback<map.MapComponentController>; // 初始化回调
}
这三个属性都是 private(私有的),只在组件内部使用。都带 ? 表示可选,初始值为 undefined,在 init() 方法里初始化。
三、初始化 mapOptions
async init(): Promise<void> {
// 配置地图初始化选项
this.mapOptions = {
position: {
target: {
latitude: this.latitude, // 初始中心点纬度(初始为0)
longitude: this.longitude, // 初始中心点经度(初始为0)
},
zoom: 16, // 初始缩放级别(1-20,16约等于街道级别)
},
myLocationControlsEnabled: true, // 显示"我的位置"按钮
mapType: mapCommon.MapType.STANDARD, // 地图类型:标准地图
};
}
3.1 zoom 缩放级别
| zoom 值 | 显示范围 |
|---|---|
| 1 | 全球视图 |
| 5 | 国家/大陆 |
| 10 | 城市 |
| 15 | 街区 |
| 16 | 街道(本项目使用) |
| 20 | 建筑物 |
3.2 mapType 地图类型
| 类型 | 说明 |
|---|---|
STANDARD |
标准矢量地图(本项目使用) |
SATELLITE |
卫星图 |
TERRAIN |
地形图 |
NONE |
空白底图 |
3.3 myLocationControlsEnabled
设为 true 会在地图右下角显示一个"定位到我的位置"按钮(蓝色圆点按钮),用户点击后地图自动跳到当前位置。
四、初始化回调(Callback)
这是 MapKit 最关键的部分。当地图组件创建完成后,通过回调函数返回 MapComponentController:
// 定义回调
this.callback = async (err, mapController): Promise<void> => {
// 错误处理
if (err) {
Logger.error('testTag', `init fail, code: ${err.code}, message: ${err.message}`);
return;
}
// 获取到控制器,保存下来
this.mapController = mapController;
// 从这里开始,可以操作地图了
// 1. 开启"我的位置"图层(蓝色小点显示当前位置)
this.mapController.setMyLocationEnabled(true);
// 2. 监听"我的位置"按钮点击
this.mapController.on('myLocationButtonClick', () => {
Logger.info('testTag', 'Jump to my location');
mapUtil.moveToMyLocation(mapController).then(() => {
this.isShow = true;
});
});
// 3. 监听地图标记(Marker)点击
this.mapController.on('markerClick', (marker) => {
this.isShow = true;
marker.setInfoWindowVisible(true);
this.curMarker = marker;
this.imageScale = 1.5;
mapUtil.imageAnimation(marker, this.imageScale);
mapUtil.moveToCurrentPosition(
marker.getPosition().latitude,
marker.getPosition().longitude,
mapController
);
});
// 4. 初始化时移动到当前位置
mapUtil.moveToMyLocation(mapController);
// 5. 获取当前位置坐标
this.currentLatitude = (await mapUtil.getMyLocation()).latitude;
this.currentLongitude = (await mapUtil.getMyLocation()).longitude;
this.latitude = this.currentLatitude;
this.longitude = this.currentLongitude;
// 6. 给每个加油站添加地图标记
this.stationInfoList.forEach(async (stationItem: StationData) => {
await mapUtil.addMapMaker(
stationItem.latitude,
stationItem.longitude,
this.mapController as map.MapComponentController
);
});
};
提示:所有对地图的操作(移动镜头、添加标记、监听事件)都必须在 callback 被调用之后进行,因为此时
mapController才准备好了。这是最常见的初学者踩坑点。
五、在 build() 里放置 MapComponent
build() {
NavDestination() {
Stack() {
// 地图组件:占满全屏
MapComponent({
mapOptions: this.mapOptions, // 传入配置
mapCallback: this.callback, // 传入回调(地图就绪时被调用)
});
// 叠加在地图上的标题栏
this.titleBuilder();
}
.width(Constants.FULL_PERCENT)
.height(Constants.FULL_PERCENT)
// ...
}
}
MapComponent 接受两个参数:
mapOptions:地图初始配置mapCallback:地图就绪回调
地图组件渲染完成后,会调用 mapCallback,把 MapComponentController 传给你,你就可以开始操控地图了。
六、setMyLocationEnabled:显示当前位置
this.mapController.setMyLocationEnabled(true);
调用这个方法后,地图上会在用户当前位置显示一个蓝色光晕圆点,实时更新用户位置。
这个功能需要定位权限,所以必须在权限申请成功后才有效(项目在主页进入时就申请了权限,所以这里通常已经有权限了)。
七、地图事件监听
7.1 监听"我的位置"按钮点击
this.mapController.on('myLocationButtonClick', () => {
Logger.info('testTag', 'Jump to my location');
mapUtil.moveToMyLocation(mapController).then(() => {
this.isShow = true; // 显示底部加油站列表
});
});
用户点击地图右下角的定位按钮,地图镜头自动跳到用户位置,同时显示底部列表。
7.2 监听 Marker 点击
this.mapController.on('markerClick', (marker) => {
this.isShow = true;
marker.setInfoWindowVisible(true); // 显示标记的信息窗口
this.curMarker = marker; // 记录当前点击的标记
this.imageScale = 1.5; // 放大比例
mapUtil.imageAnimation(marker, this.imageScale); // 播放放大动画
mapUtil.moveToCurrentPosition(
marker.getPosition().latitude,
marker.getPosition().longitude,
mapController
);
});
用户点击地图上的加油站标记时:
- 显示底部列表(
isShow = true) - 显示标记的信息窗口
- 记录当前标记(用于后续取消动画)
- 播放标记放大动画(视觉反馈)
- 地图镜头移动到该标记位置
八、MapKit 事件类型
mapController.on(event, callback) 支持的常用事件:
| 事件 | 触发时机 |
|---|---|
markerClick |
点击 Marker 标记 |
mapClick |
点击地图空白区域 |
myLocationButtonClick |
点击"我的位置"按钮 |
cameraChange |
地图镜头位置改变 |
cameraChangeFinish |
地图镜头停止移动 |
mapLoad |
地图底图加载完成 |
九、完整流程图
onWillAppear()
└─> init()
├─> STATION_LIST → stationInfoList
├─> 创建 mapOptions(初始配置)
└─> 创建 callback(等待地图就绪)
MapComponent 渲染
└─> 地图就绪,调用 callback(null, mapController)
├─> 保存 mapController
├─> setMyLocationEnabled(true) // 显示位置蓝点
├─> on('myLocationButtonClick') // 监听定位按钮
├─> on('markerClick') // 监听标记点击
├─> moveToMyLocation() // 定位到当前位置
├─> getMyLocation() // 获取坐标(用于距离计算)
└─> forEach → addMapMaker() // 为每个加油站添加标记
总结
MapKit 接入的核心流程:
- 声明变量:
mapOptions、mapController、callback - 配置 mapOptions:设置初始位置、缩放级别、地图类型
- 定义 callback:地图就绪后获取 controller,做所有初始化操作
- 放置 MapComponent:传入 options 和 callback
- 在 callback 里操控地图:监听事件、移动镜头、添加标记
下一篇讲坐标系转换——WGS84(GPS坐标)和 GCJ02(国内地图坐标)有什么区别,为什么需要转换。
更多推荐



所有评论(0)