高德地图使用vue组件自定义infoWindow信息窗口
项目背景在使用高德地图做地图相关开发时,经常会使用到标记点marker功能,如果业务较复杂,标记点需要增加自定义的信息窗口infoWindow,自定义信息窗口支持传入content参数,content 可以是 dom 对象,也可以是 html 识别的字符串。自定义最大的问题就是事件不好处理,比如关闭信息窗的点击事件。在官方的示例中,自定义使用的原生dom节点创建并添加事件,对于复杂场景,这样操作就
项目背景
在使用高德地图做地图相关开发时,经常会使用到标记点marker
功能,如果业务较复杂,标记点需要增加自定义的信息窗口infoWindow
,自定义信息窗口支持传入content
参数,content
可以是 dom
对象,也可以是 html
识别的字符串。
自定义最大的问题就是事件不好处理,比如关闭信息窗的点击事件。在官方的示例中,自定义使用的原生dom
节点创建并添加事件,对于复杂场景,这样操作就显得较为复杂,可读性和拓展性都很差。这里可以使用es6
的模板语法做html
字符串拼接,把需要绑定事件的元素设置ID,在创建信息窗后,通过addEventListener
进行点击事件绑定。
在更复杂的业务场景中,es6
的模板语法显得力不从心,比如我想使用element-ui
组件,自定义的svg
图标组件。为了更灵活的进行信息窗自定义,我们可以选择使用vue
组件作为自定义信息窗的content
。首先我们要理清逻辑,假如有多个标记点,信息窗是在标记点被点击后显示,那么我们就在标记点上添加一个点击事件,点击时,创建信息窗并显示。而不要在创建标记点时就把信息窗创建了。下面是伪代码:
伪代码
// 父组件
<template>
<div class="container">
<div v-loading="mapLoading" class="wrap">
<div id="container" style="width: 100%; height: 100%"></div>
<!-- 自定义组件InfoWindow,初始时需要隐藏 -->
<!-- 隐藏不要使用v-if,因为我们需要渲染完成后的原生html结构作为信息框的dom对象使用 -->
<InfoWindow v-show="showInfoWindow" ref="infoWindow" :info-window="infoWindow"></InfoWindow>
</div>
</div>
</template>
<script>
//引入定义的信息窗组件
import InfoWindow from './components/InfoWindow'
export default {
components: {
// 注册组件
InfoWindow,
},
data() {
return {
// 组件加载后隐藏
showInfoWindow: false,
infoWindow: {}
}
},
methods: {
addMarker() {
// 创建标记点Marker
let labelMarker = new this.AMap.LabelMarker({
icon: 'icon路径',
position: 'position定位点'
})
// labelMarker都绑定上点击事件
labelMarker.on('click', (e) => {
// 点击后创建自定义信息窗口
this.setInfoWindows(title, content, e)
// 把地图中心点设置为当前点击的标记点
this.map.setZoomAndCenter(this.zoom, item.position)
})
},
setInfoWindows(title, content, e) {
// 此时需要把组件的样式设置为可见
this.showInfoWindow = true
// 设置marker头部的标题信息窗口
const infoWindow = new this.AMap.InfoWindow({
// 使用自定义窗体
isCustom: true,
// 只有当组件渲染完毕后,通过$el才能拿到原生的dom对象
content: this.$refs['infoWindow'].$el,
// 设置定位偏移量
offset: new this.AMap.Pixel(-9, -60)
})
this.infoWindow = infoWindow
// 信息窗口打开
infoWindow.open(this.map, e.target.getPosition())
}
}
}
</script>
// 信息窗口子组件
<template>
<div>
<el-card class="box-card" style="padding: 0 80 30 80;width: 400px;border-radius: 10px;">
<div id="del-div">
<el-link type="primary" icon="el-icon-close" @click="close()"></el-link>
</div>
<div style="text-align: center;">
<el-button type="primary">主要按钮</el-button>
</div>
</div>
</template>
<script>
export default {
props: {
infoWindow: {
type: Object,
default: () => {}
},
},
methods: {
// 关闭
close() {
// 高德地图信息窗关闭的api
this.infoWindow.close()
},
edit() {
console.log('编辑按钮测试')
},
del() {
console.log('删除按钮测试')
}
}
}
</script>
<style lang="css" scoped>
#del-div {
position: absolute;
right: 20;
top: 20;
transform: scale(1.2);
}
</style>
把信息窗口封装成vue
组件后,灵活性更强,其它组件都可以在里面使用。但是要注意,上面都是伪代码,需要理解后根据实际业务把代码加进去。
参考博客:
更多推荐
所有评论(0)