Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Hmos Map Kit Event Listening

ASecurity

监听地图事件,支持点击、长按、相机移动、标记点击、我的位置按钮点击、点注释点击等多种事件类型,适用于地图交互场景

2 stars
0 votes
0 copies
0 views
Added 9/22/2026
developmenttypescriptgitapi

Works with

cliapi

Security Analysis

A100/100

Scanned 9/22/2026

Install to Claude Code

$npx -y skills add IsKenKenYa/skills --skill hmos-map-kit-event-listening --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Hmos Map Kit Event Listening?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Hmos Map Kit Event Listening
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/iskenkenya-hmos-map-kit-event-listening/badge)](https://www.skillsdirectory.com/skills/iskenkenya-hmos-map-kit-event-listening)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SUB_SKILL.md
---
name: hmos-map-kit-event-listening
description: 监听地图事件,支持点击、长按、相机移动、标记点击、我的位置按钮点击、点注释点击等多种事件类型,适用于地图交互场景
---

# 地图事件监听技能

## 功能描述

本技能提供HarmonyOS Map Kit地图事件监听功能,通过MapEventManager实现对地图的点击、长按、相机移动、标记点击、我的位置按钮点击、点注释点击等事件的监听。支持注册多个回调函数,支持取消特定回调或全部回调。

**核心能力**:
- 地图点击事件监听(mapClick)
- 地图长按事件监听(mapLongClick)
- 相机移动事件监听(cameraMoveStart、cameraMove、cameraIdle)
- 标记点击事件监听(markerClick)
- 我的位置按钮点击事件监听(myLocationButtonClick)
- 点注释点击事件监听(pointAnnotationClick)

**适用范围**:HarmonyOS Stage模型应用开发,需要地图交互功能的场景。

**限制条件**:
- 仅支持Stage模型
- 需要地图组件已初始化完成
- API版本要求:5.0.0(12)及以上

**典型场景**:
- 地图点击获取坐标位置
- 地图拖动实时监控相机状态
- 标记点击展示详细信息
- 我的位置按钮点击触发定位功能

## 使用场景

### 触发词
- "监听地图点击"
- "监听地图长按"
- "监听相机移动"
- "监听标记点击"
- "监听我的位置按钮"
- "监听点注释点击"
- "地图事件监听"
- "MapEventManager"

### 能做
- 注册地图事件监听器
- 支持同一事件注册多个回调函数
- 获取点击位置的经纬度坐标
- 监听相机移动的开始、进行、结束状态
- 监听标记、点注释等覆盖物的点击事件
- 取消特定回调或全部回调

### 绝不做
- 不处理地图初始化相关功能
- 不处理地图覆盖物的创建和添加
- 不处理地图样式设置
- 不处理地图导航功能
- 不处理超出Map Kit范围的事件

### 补充
- 需先获取MapEventManager实例:`mapController.getEventManager()`
- 支持传递多个callback异步回调,可根据需要取消特定回调或全部回调
- 相机移动事件的回调参数reason表示移动原因:1-用户手势、2-用户交互动画、3-开发人员启动动画
- 所有事件监听方法需在地图初始化回调或自定义方法中执行

## 调用规范和规则

### 输入约束
- mapController实例必须已初始化
- callback函数类型必须与事件类型匹配
- 经纬度范围:latitude [-90, 90],longitude [-180, 180]
- 相机移动原因值:1、2、3(仅cameraMoveStart事件)

### 执行约束
- 最大回调函数数量:无限制(支持多个回调)
- 事件监听必须在地图加载后执行
- 取消监听时,callback为空取消所有回调,callback非空取消指定回调
- 建议在aboutToAppear或地图初始化回调中设置监听

### 内容约束
- 禁止在地图初始化前调用监听方法
- 禁止使用错误的callback参数类型
- 禁止在回调函数中执行耗时操作(建议不超过100ms)
- 回调函数中禁止直接修改UI状态(需使用异步方式)

### 降级约束
- mapController获取失败:提示用户地图未初始化,延迟执行监听设置
- callback类型错误:记录日志并忽略该回调
- 事件监听失败:使用默认处理逻辑,记录异常日志
- 多次注册同一callback:自动去重,避免重复触发

## 调用流程和步骤

### 步骤1:初始化地图组件并获取事件管理器

**前置校验**:
1. 确认已导入Map Kit模块:`import { map, mapCommon } from '@kit.MapKit'`
2. 确认地图组件已添加到页面布局
3. 确认mapController实例已初始化

**获取MapEventManager**:
```typescript
import { MapComponent, mapCommon, map } from '@kit.MapKit';
import { AsyncCallback } from '@kit.BasicServicesKit';

@Entry
@Component
struct MapEventDemo {
  private mapController?: map.MapComponentController;
  private mapEventManager?: map.MapEventManager;
  
  aboutToAppear(): void {
    let mapOptions: mapCommon.MapOptions = {
      position: {
        target: { latitude: 39.9, longitude: 116.4 },
        zoom: 10
      }
    };
    
    let callback: AsyncCallback<map.MapComponentController> = async (err, mapController) => {
      if (!err && mapController) {
        this.mapController = mapController;
        // 获取事件管理器
        this.mapEventManager = this.mapController.getEventManager();
        // 注册事件监听
        this.setupEventListeners();
      }
    };
  }
  
  private setupEventListeners(): void {
    // 在此方法中注册所有事件监听
  }
  
  build() {
    Stack() {
      MapComponent({ mapOptions: this.mapOptions, mapCallback: this.callback })
        .width('100%')
        .height('100%')
    }
  }
}
```

### 步骤2:注册地图点击事件监听

**示例代码**:
```typescript
private setupMapClickListener(): void {
  if (!this.mapEventManager) {
    console.error('MapEventManager not initialized');
    return;
  }
  
  // 注册点击事件回调
  let clickCallback = (position: mapCommon.LatLng) => {
    console.info('mapClick', `Clicked position: lat=${position.latitude}, lng=${position.longitude}`);
    // 处理点击位置,例如添加标记、显示信息等
    this.handleMapClick(position);
  };
  
  this.mapEventManager.on('mapClick', clickCallback);
}

private handleMapClick(position: mapCommon.LatLng): void {
  // 业务处理逻辑
  // 注意:不要在回调中直接执行耗时操作
}
```

### 步骤3:注册地图长按事件监听

**示例代码**:
```typescript
private setupMapLongClickListener(): void {
  if (!this.mapEventManager) {
    console.error('MapEventManager not initialized');
    return;
  }
  
  let longClickCallback = (position: mapCommon.LatLng) => {
    console.info('mapLongClick', `Long clicked position: lat=${position.latitude}, lng=${position.longitude}`);
    // 处理长按事件,例如弹出菜单、选择操作等
  };
  
  this.mapEventManager.on('mapLongClick', longClickCallback);
}
```

### 步骤4:注册相机移动事件监听

**示例代码**:
```typescript
private setupCameraMoveListeners(): void {
  if (!this.mapEventManager) {
    console.error('MapEventManager not initialized');
    return;
  }
  
  // 相机开始移动
  let moveStartCallback = (reason: number) => {
    console.info('cameraMoveStart', `Camera move started, reason: ${reason}`);
    // reason: 1-用户手势, 2-用户交互动画, 3-开发人员启动动画
  };
  this.mapEventManager.on('cameraMoveStart', moveStartCallback);
  
  // 相机移动中
  let moveCallback = () => {
    console.info('cameraMove', 'Camera is moving');
  };
  this.mapEventManager.on('cameraMove', moveCallback);
  
  // 相机移动结束
  let idleCallback = () => {
    console.info('cameraIdle', 'Camera move ended');
    // 可以在此获取最终的相机位置
  };
  this.mapEventManager.on('cameraIdle', idleCallback);
}
```

### 步骤5:注册标记点击事件监听

**示例代码**:
```typescript
private setupMarkerClickListener(): void {
  if (!this.mapEventManager) {
    console.error('MapEventManager not initialized');
    return;
  }
  
  let markerClickCallback = (marker: map.Marker) => {
    console.info('markerClick', `Marker clicked, id: ${marker.getId()}`);
    // 处理标记点击,例如显示信息窗口、跳转详情页等
    this.showMarkerInfo(marker);
  };
  
  this.mapEventManager.on('markerClick', markerClickCallback);
}

private showMarkerInfo(marker: map.Marker): void {
  // 显示标记详细信息
}
```

### 步骤6:注册我的位置按钮点击事件监听

**示例代码**:
```typescript
private setupMyLocationButtonClickListener(): void {
  if (!this.mapEventManager) {
    console.error('MapEventManager not initialized');
    return;
  }
  
  let myLocationCallback = () => {
    console.info('myLocationButtonClick', 'My location button clicked');
    // 触发定位功能或更新位置显示
  };
  
  this.mapEventManager.on('myLocationButtonClick', myLocationCallback);
}
```

### 步骤7:注册点注释点击事件监听

**示例代码**:
```typescript
private setupPointAnnotationClickListener(): void {
  if (!this.mapEventManager) {
    console.error('MapEventManager not initialized');
    return;
  }
  
  let pointAnnotationCallback = (pointAnnotation: map.PointAnnotation) => {
    console.info('pointAnnotationClick', `PointAnnotation clicked, id: ${pointAnnotation.getId()}`);
    // 处理点注释点击,例如展示信息窗口等
  };
  
  this.mapEventManager.on('pointAnnotationClick', pointAnnotationCallback);
}
```

### 步骤8:取消事件监听

**取消特定回调**:
```typescript
private removeSpecificCallback(): void {
  if (!this.mapEventManager) {
    return;
  }
  
  // 定义回调函数(需与注册时相同的引用)
  let clickCallback = (position: mapCommon.LatLng) => {
    console.info('mapClick', `Position: ${position.latitude}`);
  };
  
  // 先注册
  this.mapEventManager.on('mapClick', clickCallback);
  
  // 后取消特定回调
  this.mapEventManager.off('mapClick', clickCallback);
}
```

**取消所有回调**:
```typescript
private removeAllCallbacks(): void {
  if (!this.mapEventManager) {
    return;
  }
  
  // 取消mapClick事件的所有回调
  this.mapEventManager.off('mapClick');
  
  // 取消其他事件的所有回调
  this.mapEventManager.off('mapLongClick');
  this.mapEventManager.off('cameraMoveStart');
  this.mapEventManager.off('cameraMove');
  this.mapEventManager.off('cameraIdle');
  this.mapEventManager.off('markerClick');
  this.mapEventManager.off('myLocationButtonClick');
  this.mapEventManager.off('pointAnnotationClick');
}
```

### 步骤9:错误处理

**示例代码**:
```typescript
private setupEventListenersWithErrorHandling(): void {
  try {
    if (!this.mapController) {
      console.error('MapController not initialized');
      return;
    }
    
    this.mapEventManager = this.mapController.getEventManager();
    
    if (!this.mapEventManager) {
      console.error('Failed to get MapEventManager');
      return;
    }
    
    // 注册事件监听
    this.mapEventManager.on('mapClick', (position: mapCommon.LatLng) => {
      try {
        this.handleMapClick(position);
      } catch (error) {
        console.error('Error in mapClick callback:', error);
      }
    });
    
  } catch (error) {
    console.error('Failed to setup event listeners:', error);
    // 降级处理:延迟重试或使用默认处理
    this.retrySetupListeners();
  }
}

private retrySetupListeners(): void {
  // 延迟重试逻辑
  setTimeout(() => {
    console.info('Retrying to setup event listeners...');
    this.setupEventListenersWithErrorHandling();
  }, 1000);
}
```

## 错误码说明

本技能涉及的主要错误类型及解决方法:

| 错误类型 | 说明 | 解决方法 |
|---------|------|---------|
| MapController未初始化 | mapController实例为null或undefined | 确保在地图初始化回调中获取mapController后再设置监听 |
| MapEventManager获取失败 | getEventManager()返回null | 检查地图组件是否正确初始化,重新调用地图初始化流程 |
| Callback类型错误 | 回调函数参数类型不匹配 | 参考API文档确认正确的callback参数类型:mapClick/mapLongClick使用LatLng,markerClick使用Marker等 |
| 事件类型错误 | on/off方法的事件类型字符串错误 | 使用正确的事件类型字符串:'mapClick', 'mapLongClick', 'cameraMoveStart'等 |
| Callback未注册 | off取消未注册的callback | 确保callback已通过on方法注册,或直接调用off取消所有回调 |
| 回调函数执行异常 | 回调函数内部逻辑错误 | 在回调函数内部添加try-catch,避免异常影响后续回调执行 |

## 编译和修复问题

### 依赖声明
```json
{
  "dependencies": {
    "@kit.MapKit": "HarmonyOS SDK 5.0.0(12)及以上"
  }
}
```

### 环境要求
- HarmonyOS SDK版本:5.0.0(12)及以上
- DevEco Studio版本:5.0及以上
- 运行环境:Stage模型应用
- 系统能力:SystemCapability.Map.Core

### 常见编译问题

**问题1:导入模块失败**
```
Error: Cannot find module '@kit.MapKit'
```
**解决方法**:确保HarmonyOS SDK已正确安装,在oh-package.json5中添加依赖配置,执行ohpm install。

**问题2:MapComponent组件未找到**
```
Error: Component 'MapComponent' is not found
```
**解决方法**:正确导入MapComponent:`import { MapComponent, mapCommon, map } from '@kit.MapKit'`。

**问题3:Callback类型不匹配**
```
Type 'Callback<void>' is not assignable to type 'Callback<LatLng>'
```
**解决方法**:参考API文档,使用正确类型的callback函数。mapClick/mapLongClick需使用`Callback<mapCommon.LatLng>`,markerClick需使用`Callback<map.Marker>`。

**问题4:Stage模型限制**
```
Error: This interface can only be used in Stage model
```
**解决方法**:确认应用使用Stage模型,检查module.json5中的配置。

## 常见问题与解决方法

### Q1:如何判断地图是否已初始化完成?
**原因**:事件监听需要在地图初始化后才能设置,否则mapController为null。
**解决方法**:
- 在地图初始化回调函数中设置监听
- 使用mapLoad事件监听地图加载完成后再设置其他监听
- 在自定义方法中检查mapController是否存在

### Q2:同一个事件可以注册多个回调吗?
**原因**:on方法支持传递多个callback异步回调。
**解决方法**:
- 多次调用on方法注册不同的callback函数
- 每个callback独立触发,顺序执行
- 使用off方法可取消特定callback或全部callback

### Q3:如何获取点击位置的详细信息?
**原因**:mapClick事件只返回经纬度坐标,需要额外获取其他信息。
**解决方法**:
- 使用经纬度坐标进行逆地理编码
- 使用经纬度坐标查询POI信息
- 根据经纬度坐标添加标记或覆盖物

### Q4:相机移动事件频繁触发怎么办?
**原因**:cameraMove事件在相机移动过程中会多次触发。
**解决方法**:
- 使用cameraMoveStart和cameraIdle事件处理开始和结束
- 在cameraMove回调中避免执行耗时操作
- 使用防抖或节流机制控制回调执行频率

### Q5:如何区分用户手势和程序控制导致的相机移动?
**原因**:cameraMoveStart事件的回调参数reason表示相机移动原因。
**解决方法**:
- reason=1:用户手势(拖动、缩放等)
- reason=2:用户交互产生的默认动画
- reason=3:开发人员启动的动画(animateCamera等)
- 根据reason值执行不同的业务逻辑

## 输出结果报告

执行地图事件监听设置后,输出以下信息:

```json
{
  "status": "success",
  "mapEventManager": "MapEventManager实例已获取",
  "registeredEvents": [
    "mapClick",
    "mapLongClick",
    "cameraMoveStart",
    "cameraMove",
    "cameraIdle",
    "markerClick",
    "myLocationButtonClick",
    "pointAnnotationClick"
  ],
  "apiUsed": [
    "MapComponentController.getEventManager()",
    "MapEventManager.on()",
    "MapEventManager.off()"
  ],
  "description": "已成功注册地图事件监听器,可在回调函数中处理相应事件"
}
```

## 参考文档

- [API开发指南:事件交互](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/map-listening)
- [API参考说明:MapEventManager](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/map-map-mapeventmanager)
- [API参考说明:MapComponentController](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/map-map-mapcomponentcontroller)
- [API参考说明:mapCommon.LatLng](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/map-common)
- [API参考说明:Marker](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/map-map-marker)
- [API参考说明:PointAnnotation](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/map-map-pointannotation)
- [开发指南:标记](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/map-marker)
- [开发指南:点注释](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/map-annotation)
- [开发指南:显示我的位置](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/map-location)

## 完整示例代码

- [ArkTS完整示例](assets/map_event_listener_example.ets)

## 测试用例

### 正向测试用例
- [测试地图点击事件监听](tests/test_map_click.ts):验证mapClick事件正确触发并返回经纬度
- [测试相机移动事件监听](tests/test_camera_move.ts):验证cameraMoveStart/cameraMove/cameraIdle事件顺序触发
- [测试标记点击事件监听](tests/test_marker_click.ts):验证markerClick事件正确触发并返回Marker对象
- [测试多个回调注册](tests/test_multiple_callbacks.ts):验证同一事件注册多个callback均能触发

### 边界测试用例
- [测试经纬度边界值](tests/test_latlng_boundary.ts):验证点击位置latitude[-90,90]、longitude[-180,180]边界值处理
- [测试相机移动原因值](tests/test_camera_reason.ts):验证reason参数值1、2、3的正确处理
- [测试大量回调注册](tests/test_many_callbacks.ts):验证注册10个以上callback的性能和正确性

### 异常测试用例
- [测试MapController未初始化](tests/test_no_controller.ts):验证地图未初始化时设置监听的错误处理
- [测试Callback类型错误](tests/test_wrong_callback_type.ts):验证使用错误callback类型的错误提示
- [测试取消未注册的Callback](tests/test_remove_unregistered.ts):验证取消未注册callback的处理逻辑
- [测试回调函数异常](tests/test_callback_exception.ts):验证回调函数抛出异常不影响其他回调执行

Attribution

IsKenKenYaIsKenKenYa
View sourceMore from IsKenKenYa →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

284072 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2192 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →