高德地图中使用 Vue 组件自定义Marker标点或InfoWindow信息窗体

原理

在高德地图中使用Vue组件进行自定义Marker、InfoWindow

new AMap.Marker(opts: MarkerOptions)

new AMap.InfoWindow(opts: InfoOptions)

属性 描述
opts.content 类型:`(string HTMLElement)`

查看文档可以知道 content 的属性可以接收HTMLElement元素,我们可以通过创建一个HTMLElement元素,然后将vue组件挂载到这个元素上。

代码示例

  • vue3
  • ts
  • amap-jsapi-loader

CreateHTML.ts 创建元素

使用createApp创建vue实例,传入组件

返回元素、vue实例(这个实例返回很重要)

ts 复制代码
/**
 * 创建vue元素
 */
export const createHTML = (comp: Component, props?: Record<string, unknown>) => {
  const element = document.createElement('div')
  const app = createApp(comp, props)
  app.mount(element)

  return {
    element, app
  }
}

vue组件

vue 复制代码
<script setup lang="ts">
defineOptions({
  name: 'Marker'
})
const props = defineProps<{
  name: string
}>()
</script>

<template>
  <h2>{{ props.name }}</h2>
</template>

<style scoped>
h2 {
  background: #115c5c;
  padding: 5px 10px;
  border-radius: 5px;
}
</style>

创建自定义Marker

拿Marker做个示例 InfoWindow同理

ts 复制代码
// 创建vue元素
const {app,element} = createHTML(MyComp,{
    name: '这是一个自定义的Marker',
})

// 创建覆盖物
const marker = new AMap.Marker({
    content: element,
    // ...otherConf
})

// 添加到地图
map.add(marker)

这样就创建了一个自定义Marker。我们也可以在vue调试工具中看到这个App实例。

这样本来是没什么问题的,但是......

当我们将marker销毁的时候App实例仍然存在,所以当我们对marker(InfoWindow)进行移除的同时,需要把App的实例也进行销毁。

ts 复制代码
// 移除标点
marker.remove()
// 销毁app
app.unmount()

扩展

使用pinia 或者组件库

由于我们是创建了一个新的vue实例,如果我们要在组件内使用pinia、或者其他组件库、插件,我们需要再写一遍配置

修改创建HTML方法

ts 复制代码
/**
 * 创建vue元素
 */
export const createHTML = (comp: Component, props?: Record<string, unknown>) => {
  const element = document.createElement('div')
  const app = createApp(comp, props)

  /** 引入pinia 或者其他配置**/
  
  // 引入相同的pinia 可以与其他实例通过pinia进行通信
  app.use(pinia)
  
  /** 引入pinia **/
  

  app.mount(element)

  return {
    element, app
  }
}

新的问题

问题1

由于组件动态生成,生成后异步获取数据,元素依旧可能变化,最后生成的元素高度、宽度可能不定,导致Marker、InfoWindow生成的位置不正确。

不完全解决办法

  1. 固定元素宽高
  2. 不在组件内异步获取数据,在组件外获取数据后再传入组件,生成Marker
相关推荐
2401_85743969几秒前
智慧社区电商系统:提升用户体验的界面设计
前端·javascript·php·ux
我是高手高手高高手10 分钟前
ThinkPHP8多应用配置及不同域名访问不同应用的配置
linux·服务器·前端·php
csdnLN39 分钟前
$.ajax() 对应事件done() 、fail()、always() 的用法
前端·javascript·ajax
甜味橘阳40 分钟前
echarts地图可视化展示
前端·javascript·echarts
bloxed1 小时前
前端文件下载多方式集合
前端·filedownload
余生H1 小时前
前端Python应用指南(三)Django vs Flask:哪种框架适合构建你的下一个Web应用?
前端·python·django
LUwantAC2 小时前
CSS(四)display和float
前端·css
cwtlw2 小时前
CSS学习记录20
前端·css·笔记·学习
界面开发小八哥2 小时前
「Java EE开发指南」如何用MyEclipse构建一个Web项目?(一)
java·前端·ide·java-ee·myeclipse
米奇妙妙wuu2 小时前
react使用sse流实现chat大模型问答,补充css样式
前端·css·react.js