目录
index.ts
// src/utils/loadTMap.ts
declare global {interface Window {TMap?: any;}
}
// 参数名就是腾讯地图的Key
export function loadTMap(key: string): Promise<void> {console.log(key,"key")return new Promise((resolve, reject) => {if (window.TMap) {resolve()return}const script = document.createElement('script')script.type = 'text/javascript'//&libraries=service 这个加上 才可以使用地图的一些方法script.src = `https://map.qq.com/api/gljs?v=1.exp&key=${key}&libraries=service`script.async = truescript.onload = () => {if (window.TMap) {resolve()} else {reject(new Error('TMap 未正确加载'))}}script.onerror = () => reject(new Error('腾讯地图脚本加载失败'))document.head.insertBefore(script, document.head.firstChild)})
}
index.vue
<template><div><div id="container" ref="mapContainer"></div></div>
</template><script setup lang="ts">
import { ref, defineExpose } from 'vue'
import { loadTMap } from './index' // 你封装的腾讯地图加载器import { ElMessage } from 'element-plus'// 类型定义
interface Position {lat: numberlng: number
}interface GeocoderResultDetail {location: Position, //经纬度address: string ,//详细地址[key: string]: any //省市区
}// Props
const props = withDefaults(defineProps<{lat?: numberlon?: numbermapKey: string,region?:string //城市
}>(), {lat: 30.570676,lon: 104.065173,region:"成都市"
})// Emits
const emit = defineEmits<{(e: 'getCoordinates', detail: GeocoderResultDetail): void
}>()const mapContainer = ref<HTMLElement | null>(null)
const mapInstance = ref<any>(null)
const geocoder = ref<any>(null)
const marker = ref<any>(null)
const resultDetail = ref<GeocoderResultDetail | null>(null)
const hasLoaded = ref(false)
const TMap=ref()
// 初始化地图
const initMap = async () => {if (hasLoaded.value) returntry {if (!props.mapKey) return console.warn('地图Key为空')await loadTMap(props.mapKey)const TMap = window.TMapif (!TMap || !mapContainer.value) throw new Error('TMap 加载失败')const center = new TMap.LatLng(props.lat, props.lon)mapInstance.value = new TMap.Map(mapContainer.value, {center,zoom: 15})// 初始化地理编码器geocoder.value = new TMap.service.Geocoder()// 初始点反查地址geocoder.value.getAddress({ location: center })// 点击地图获取坐标并反查地址mapInstance.value.on('click', (e: any) => {const latLng = new TMap.LatLng(e.latLng.lat, e.latLng.lng)setMarker(latLng)geocoder.value.getAddress({location: latLng,success: (res: { result: GeocoderResultDetail }) => {resultDetail.value = res.resultconsole.log("哈哈哈", res.result)// emit('getCoordinates', {// location: latLng,// })},fail: (err: any) => {console.error('地址解析失败:', err)}})})hasLoaded.value = true} catch (error) {console.error('地图初始化失败:', error)}
}// 打点函数
const setMarker = (latLng: Position) => {if (marker.value) marker.value.setMap(null)
const center = new window.TMap.LatLng(latLng.lat, latLng.lng)const point = new window.TMap.LatLng(latLng.lat, latLng.lng)// 设置地图中心点mapInstance.value.setCenter(center)try{marker.value = new window.TMap.MultiMarker({map: mapInstance.value,styles: {marker: new window.TMap.MarkerStyle({width: 25,height: 35,anchor: { x: 16, y: 32 },src: 'https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/markerDefault.png'})},geometries:[{"id": "1","styleId": 'marker',"position": point,"properties": {"title": "marker4"}}]})geocoder.value.getAddress({location: point,}).then((res:{result:GeocoderResultDetail })=>{const {result}=resemit('getCoordinates', {type: 'getAddress',location: {lat:result.location.lat,lng:result.location.lng},address: result.address,addressInfo: {province:result.ad_info.province,city:result.ad_info.city,district:result.ad_info.district}})});}catch(err){console.log(err,"家家爱")}
}// 父组件传入地址,地图定位并打点
const setAddress = (address: string) => {if (!geocoder.value || !mapInstance.value) returngeocoder.value.getLocation({address: address,}).then((res:{result:GeocoderResultDetail })=>{const {result}=res
setMarker({lat:result.location.lat,lng: result.location.lng
})emit('getCoordinates', {type: 'getLocation',location: {lat:result.location.lat,lng:result.location.lng},address: result.address,addressInfo: {province:result.ad_info.province,city:result.ad_info.city,district:result.ad_info.district}})}).catch( (e:any) =>{console.log(e)ElMessage.error(e.message)})}// 暴露方法给父组件
defineExpose({initMap,setAddress,getMap: () => mapInstance.value
})
</script><style scoped>
#container {width: 100%;height: 450px;
}
</style>
父组件调用
<Map :mapKey="defalutKey.txMapKey" ref="tMapRef" ></Map>import Map from "@/components/map/index.vue"
const tMapRef = ref<InstanceType<typeof Map> | null>(null)
// mapKey地图key
// 中文地址转经纬度,并地图上标点
tMapRef.value?.setAddress(ruleForm.value.mer_address.trim())
tMapRef.value?.initMap()// 地图更新后, 获取更新后的数据
const getCoordinates = (data: any) => {ruleForm.value.long=data.location.lng
ruleForm.value.lat=data.location.lat
if(data.type=="getAddress"){ruleForm.value.mer_address=data.address}else{ruleForm.value.province=data.addressInfo.provinceruleForm.value.city=data.addressInfo.cityruleForm.value.district=data.addressInfo.district}
}