- 前端
- UI组件
- GIS
【免费下载链接】vue-amap
🌍 基于 Vue 2.x 和高德地图的地图组件
本文围绕 vue-amap 中的文本覆盖物组件el-amap-text展开,完整覆盖其基础用法、静态/动态属性、ref方法与事件体系;并结合仓库源码解析 Vue 组件属性是如何转换为高德AMap.Text实例、以及响应式监听与事件生命周期管理的底层机制,帮助你在 Vue 2.x 项目中把地图上的文本标注做成响应式、可交互的。
一、基础示例:在地图上渲染可点击的文本
el-amap-text用于在高德地图上渲染一段文本(高德 JS API 中的AMap.Text覆盖物)。文档(文本组件文档)给出的基础示例展示了:在el-amap容器内通过v-for循环渲染多条文本,每条文本绑定text、offset、position和events属性,点击文本时触发click回调。
<template> <div class="amap-page-container"> <el-amap vid="amapDemo" :zoom="zoom" :center="center" class="amap-demo"> <el-amap-text v-for="text in texts" :text="text.text" :offset="text.offset" :position="text.position" :events="text.events"></el-amap-text> </el-amap> </div> </template> <style> .amap-page-container { height: 200px; } </style> <script> module.exports = { data () { return { zoom: 15, center: [121.5273285, 31.21515044], texts: [ { position: [121.5273285, 31.21515044], text: 'hello world', offset: [0, 0], events: { click: () => { alert('click text'); } } } ] } } }; </script>使用前需按 快速上手文档 完成vue-amap的引入与initAMapApiLoader初始化(配置高德 key、插件与 SDK 版本),然后在模板中嵌套使用el-amap-text。
二、组件是如何工作的:源码级实现链路
阅读 amap-text.vue 可以看清el-amap-text的实现非常精简:它本身没有模板(<template></template>为空),核心逻辑全部来自公共混入 register-component.js:
// src/lib/components/amap-text.vue import registerMixin from '../mixins/register-component'; const TAG = 'el-amap-text'; export default { name: TAG, mixins: [registerMixin], props: { /* text、position、offset、zIndex 等 */ }, data() { return { handlers: { zIndex(index) { this.setzIndex(index); }, visible(flag) { flag === false ? this.hide() : this.show(); } }, amapTagName: TAG }; }, methods: { __initComponent(options) { this.$amapComponent = new AMap.Text(options); } } };从源码结构看,其初始化链路如下(均在 register-component.js 中):
- 等待地图 API 就绪:
mounted钩子中通过lazyAMapApiLoaderInstance.load()确保高德 JS API 加载完成后,才执行组件初始化;若父级地图实例$amap尚未就绪,则监听AMAP_READY_EVENT事件(常量定义见 constant.js)后再注册; - 属性转换(convertProps):
convertSignalProp依据 prop 上的$type声明做类型转换。el-amap-text中position声明为$type: 'LngLat'、offset声明为$type: 'Pixel',转换函数来自 convert-helper.js 的commonConvertMap,例如把数组[121.52, 31.21]转成new AMap.LngLat(lng, lat)、[0, 0]转成new AMap.Pixel(x, y); - 实例化:调用组件的
__initComponent,即用转换后的 options 执行new AMap.Text(options),实例保存到this.$amapComponent; - 事件注册与响应式监听:
registerRest中依次执行registerEvents()(绑定eventsprop 中的回调)、initProps()(初始化visible等只能在创建后设置的属性)、setPropWatchers()(为每个 prop 建立$watch监听,实现动态属性的响应式更新)、registerToManager()(把实例注册进AMapManager,供vid机制使用); - 销毁清理:
destroyed钩子中调用setMap(null)移除覆盖物、unregisterEvents清除所有事件监听,并逐个取消 prop 监听(unwatchFns),避免内存泄漏。
三、静态属性:仅初始化时生效
以下属性仅可以在初始化时配置,不支持响应式更新(即初始化后修改对应 prop 不会生效):
| 名称 | 类型 | 说明 |
|---|---|---|
| topWhenClick | Boolean | 鼠标点击时是否置顶,默认false,不置顶 |
| bubble | Boolean | 是否将覆盖物的鼠标或 touch 等事件冒泡到地图上,默认值:false |
| autoRotation | Boolean | 是否自动旋转。点标记在使用 moveAlong 动画时,路径方向若有变化,点标记是否自动调整角度,默认为false。广泛用于自动调节车辆行驶方向。IE8 以下不支持旋转,autoRotation 属性无效 |
| extData | Any | 用户自定义属性,支持 JavaScript API 任意数据类型,如 Marker 的 id 等 |
其中topWhenClick、bubble、autoRotation在 amap-text.vue 中均已声明为对应类型的 prop,并随convertProps()的 options 在new AMap.Text(options)时一次性传入;extData则用于把业务数据(如 id)挂到覆盖物上以便事件回调中识别。
四、动态属性:支持响应式
以下属性支持响应式更新——Vue prop 变化后,组件会通过$watch监听自动调用AMap.Text实例上对应的 setter(如setZIndex、setAngle)。监听逻辑见 register-component.js 的setPropWatchers。
| 名称 | 类型 | 说明 |
|---|---|---|
| text | String | 标记显示的文本内容 |
| position | LngLat | 点标记在地图上显示的位置,默认为地图中心点 |
| offset | Pixel | 点标记显示位置偏移量,默认值为Pixel(-10,-34)。Marker 指定 position 后,默认以 marker 左上角位置为基准点,对准所给定的 position 位置,若需使 marker 指定位置对准在 position 处,需根据 marker 的尺寸设置一定的偏移量 |
| textAlign | String | 横向位置,'left'、'right'、'center'可选 |
| verticalAlign | String | 纵向位置,'top'、'middle'、'bottom'可选 |
| draggable | Boolean | 设置点标记是否可拖拽移动,默认为false |
| raiseOnDrag | Boolean | 设置拖拽点标记时是否开启点标记离开地图的效果 |
| cursor | String | 指定鼠标悬停时的鼠标样式,自定义 cursor,IE 仅支持 cur/ani/ico 格式,Opera 不支持自定义 cursor |
| visible | Boolean | 点标记是否可见,默认为true |
| zIndex | Number | 点标记的叠加顺序。地图上存在多个点标记叠加时,通过该属性使级别较高的点标记在上层显示,默认 zIndex:100 |
| angle | Number | 点标记的旋转角度,广泛用于改变车辆行驶方向。注:angle 属性是使用 CSS3 来实现的,支持 IE9 及以上版本 |
| animation | String | 点标记的动画效果,默认值:"AMAP_ANIMATION_NONE"。可选值:"AMAP_ANIMATION_NONE"无动画效果、"AMAP_ANIMATION_DROP"点标掉落效果、"AMAP_ANIMATION_BOUNCE"点标弹跳效果 |
| shadow | Icon | 点标记阴影,不设置该属性则点标记无阴影 |
| title | String | 鼠标滑过点标记时的文字提示,不设置则鼠标滑过点标无文字提示 |
| clickable | Boolean | 点标记是否可点击 |
结合 amap-text.vue 的源码,几个值得注意的细节:
- prop 默认值:
position默认[0, 0]、offset默认[0, 0](数组形式,转换后才是AMap.LngLat/AMap.Pixel);zIndex默认100;visible默认true;clickable默认true。 - 特殊 handlers:组件通过
data().handlers对zIndex与visible提供了自定义处理函数——zIndex走setzIndex(index),visible则根据值调用hide()/show(),而不是通用的setXxxsetter。 - animation 默认值:从源码看,组件内
animation的默认值字符串被写作带中文引号的'“AMAP_ANIMATION_NONE”',实际使用时建议显式传入AMAP_ANIMATION_NONE、AMAP_ANIMATION_DROP或AMAP_ANIMATION_BOUNCE之一,以免依赖该默认值。 - position / offset 的传值:由于
$type: 'LngLat'与$type: 'Pixel'的声明,模板中直接传二元数组即可,无需手动new AMap.LngLat(...),转换由 convert-helper.js 中的toLngLat/toPixel完成。
五、ref 可用方法:获取 AMap.Text 实例
组件提供无副作用的同步帮助方法,可通过模板ref获取 Vue 组件后调用:
| 函数 | 返回 | 说明 |
|---|---|---|
| $$getInstance() | AMap.Text 实例 | 获取Text实例 |
该方法实现在公共混入 register-component.js 中,直接返回内部持有的this.$amapComponent。拿到原生实例后,即可调用高德 JS API 文档中AMap.Text的全部方法,例如:
// 模板中:<el-amap-text ref="myText" ... /> const textInstance = this.$refs.myText.$$getInstance(); // 之后可以直接调用高德原生 API textInstance.setText('新文本内容');另外,若通过AMapManager管理地图(amap-manager.js),可以给el-amap-text传入vid属性,实例会在注册时写入 manager,后续可用amapManager.getChildInstance(vid)取出该覆盖物,这在批量管理多个文本时比逐个ref更方便。
六、事件体系
eventsprop 是一个对象,key 为事件名、value 为回调函数。register-component.js 的registerEvents会遍历events并通过 event-helper.js 调用AMap.event.addListener绑定到原生实例上;组件销毁时统一clearListeners清理。文本覆盖物支持的事件如下:
| 事件 | 参数 | 说明 |
|---|---|---|
| click | MapsEvent | 鼠标左键单击事件 |
| dblclick | MapsEvent | 鼠标左键双击事件 |
| rightclick | MapsEvent | 鼠标右键单击事件 |
| mousemove | MapsEvent | 鼠标移动 |
| mouseover | MapsEvent | 鼠标移近点标记时触发事件 |
| mouseout | MapsEvent | 鼠标移出点标记时触发事件 |
| mousedown | MapsEvent | 鼠标在点标记上按下时触发事件 |
| mouseup | MapsEvent | 鼠标在点标记上按下后抬起时触发事件 |
| dragstart | MapsEvent | 开始拖拽点标记时触发事件 |
| dragging | MapsEvent | 鼠标拖拽移动点标记时触发事件 |
| dragend | MapsEvent | 点标记拖拽移动结束触发事件 |
| moving | Object | 点标记在执行 moveTo、moveAlong 动画时触发事件,Object 对象的格式是{passedPath: Array.<LngLat>},其中 passedPath 为 Marker 对象在 moveAlong 或者 moveTo 过程中已经走过的路径 |
| moveend | MapsEvent | 点标记执行 moveTo 动画结束时触发事件,也可以由 moveAlong 方法触发 |
| movealong | MapsEvent | 点标记执行 moveAlong 动画一次后触发事件 |
| touchstart | MapsEvent | 触摸开始时触发事件,仅适用移动设备 |
| touchmove | MapsEvent | 触摸移动进行中时触发事件,仅适用移动设备 |
| touchend | MapsEvent | 触摸结束时触发事件,仅适用移动设备 |
注:事件回调的参数
MapsEvent为高德 JS API 定义的事件对象(包含lnglat等字段),具体字段以高德官方 JS API 文档为准。
事件绑定示例(在 dragend 中把文本位置同步回 Vue 数据,实现“拖拽后位置持久化”):
events: { click: () => { alert('click text'); }, dragend: (e) => { // e.lnglat 为拖拽结束后的坐标 this.texts[0].position = [e.lnglat.getLng(), e.lnglat.getLat()]; } }由于eventsprop 本身也被setPropWatchers监听,动态修改events对象时会先unregisterEvents()再registerEvents(),实现事件的重新绑定。
七、实战建议与注意事项
- 区分静态与动态属性:
topWhenClick、bubble、autoRotation、extData只在初始化时生效;需要运行时变化时,应使用zIndex、visible、angle等动态属性。 - 坐标传数组即可:
position传[lng, lat]、offset传[x, y]二元数组,组件内部会自动转换为AMap.LngLat/AMap.Pixel。 - 拖拽场景:开启
:draggable="true"后,在dragend事件回调里更新响应式数据源中的position,可保证 Vue 状态与地图覆盖物位置一致。 - 文本对齐与偏移:文本类覆盖物的锚点控制主要靠
offset、textAlign、verticalAlign三个属性组合,注意offset的基准是覆盖物左上角,需要居中显示时应根据文本实际尺寸设置偏移量。 - 销毁与清理:组件在
destroyed时会自动setMap(null)并从地图移除(见 register-component.js),因此通过v-if或列表v-for删除文本时会正确卸载,无需手动调用移除方法。
参考文件
- 文本组件文档
- el-amap-text 组件源码
- 公共注册混入
- 类型转换工具
- 事件绑定工具
- AMapManager
- 快速上手
- 前端
- UI组件
- GIS
【免费下载链接】vue-amap
🌍 基于 Vue 2.x 和高德地图的地图组件
相关推荐
vue-amap el-amap-rectangle 矩形覆盖物组件:属性、事件与源码实现详解
vue amap el amap rectangle 矩形覆盖物组件:属性、事件与源码实现详解 本篇围绕 vue amap 的矩形覆盖物组件 el amap r
前端UI组件GISvue-amap 圆形覆盖物组件 el-amap-circle 完全解析:属性、事件与源码实现
vue amap 圆形覆盖物组件 el amap circle 完全解析:属性、事件与源码实现 本文基于 vue amap 仓库中 圆形组件文档 https:/
前端UI组件GISvue-amap 多边形覆盖物 el-amap-polygon 完全指南:属性、方法与源码实现解析
vue amap 多边形覆盖物 el amap polygon 完全指南:属性、方法与源码实现解析 vue amap 基于 Vue 2.x 封装了高德地图 JS
前端UI组件GIS
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考