- 安装依赖
pnpm install @amap/amap-jsapi-loader --save
- 实现组件
ReAMap
, 由useAMap.ts
和index.vue
构成
代码如下
① useAMap.ts
import { shallowRef } from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
export function useAMap() {
const map = shallowRef(null);
const initMap = async (container: string | HTMLElement, options?: object) => {
try {
const AMap = await AMapLoader.load({
key: "xxxx", // 生产环境建议将 Key 存储在配置文件中
version: "2.0",
plugins: []
});
map.value = new AMap.Map(container, {
zoom: 11,
center: [116.39, 39.9],
...options
});
} catch (error) {
console.error("地图加载失败:", error);
}
};
const destroyMap = () => {
if (map.value) {
map.value.destroy();
map.value = null;
}
};
return { map, initMap, destroyMap };
}
②index.vue
<template>
<div ref="mapContainer" class="re-amap-container" />
</template>
<script setup lang="ts">
import {
ref,
onMounted,
onUnmounted,
defineProps,
withDefaults,
defineExpose,
watch
} from "vue";
import { useAMap } from "./useAMap";
// 定义 emits
const emit = defineEmits(["map-click"]);
// 定义 props
interface Props {
options?: object;
markerOptions?: object;
infoWindow?: object;
}
const props = withDefaults(defineProps<Props>(), {
options: () => ({}),
markerOptions: null,
infoWindow: null
});
const mapContainer = ref<HTMLElement | null>(null);
const { map, initMap, destroyMap } = useAMap();
// 监听地图实例创建
watch(map, newMap => {
if (newMap) {
// 绑定地图点击事件
newMap.on("click", (e: any) => {
emit("map-click", e.lnglat);
});
// 处理标记点和信息窗
if (props.markerOptions) {
const AMap = (window as any).AMap;
const marker = new AMap.Marker(props.markerOptions);
newMap.add(marker);
if (props.infoWindow) {
const infoWindow = new AMap.InfoWindow(props.infoWindow);
marker.on("click", () => {
infoWindow.open(newMap, marker.getPosition());
});
}
}
}
});
onMounted(() => {
if (mapContainer.value) {
initMap(mapContainer.value, props.options);
}
});
onUnmounted(() => {
destroyMap();
});
// 将 map 实例暴露给父组件
defineExpose({
map
});
</script>
<style scoped>
.re-amap-container {
width: 100%;
height: 100%;
}
</style>
- 使用组件
省略了一部分代码,只贴主要的关键代码,对地图组件有什么操作,通过ref去控制即可
<script lang="ts" setup>
import { ref } from "vue";
const amapRef = ref(null);
const mapOptions = {
center: [116.39, 39.9],
zoom: 16
};
const markerOptions = {
position: [116.39, 39.9],
title: "xxx"
};
const infoWindowOptions = {
isCustom: false, // 使用高德默认样式
autoMove: true, // 点击标记点后自动平移地图,使信息窗完整显示
offset: [11, -60], // 设置信息窗的偏移量
content:
'<div style="color: #333; font-size: 14px; padding: 10px;">地址:xxxx</div>'
};
const handleMapClick = lnglat => {
console.log("地图点击位置:", lnglat);
};
</script>
<template>
<div class="h-[173px] w-[526px]">
<ReAMap
ref="amapRef"
:options="mapOptions"
:marker-options="markerOptions"
:info-window="infoWindowOptions"
@map-click="handleMapClick"
/>
</div>
</template>
实现效果可参考下图