vue3接入腾讯地图

880 阅读2分钟

vue3+vite项目,做的省级zf部门项目。之前用的高德地图,但是要收费,现在改为使用腾讯地图。

主要功能点有三个

  • 根据坐标显示地图
  • 获取当前所在地信息
  • 基于地图视图之上,点击以及搜索获取对应坐标点信息

首先 index.html中添加引用,key值在腾讯地图注册完创建应用后可见

<script charset="utf-8" src="//map.qq.com/api/js?v=2.exp&key=appKeyCode"></script>  
<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&libraries=service&key=appKeyCode"></script>

<!-- 获取当前ip所在地用 -->
<script type="text/javascript" src="https://apis.map.qq.com/tools/geolocation/min?key=appKeyCode&referer=myapp"></script>

功能点显示地图信息

<tcMap v-if="mdata.gpsLon && mdata.gpsLat" :lng="mdata.gpsLon" :lat="mdata.gpsLat" :address="mdata.ecc017" />


// tcMap.vue
<template>  
<div v-if="lng && lat" class="tcMapBase" :id="timestamp"></div>  
</template>  
  
<script lang="ts" setup name="map">  
import { onMounted,watch, ref, toRefs } from "vue";  
  
const props = defineProps({  
lat: {  
type: String,  
default: ''  
},  
lng: {  
type: String,  
default: ''  
},  
address: {  
type: String,  
default: ''  
},  
})  
  
const {lng, lat, address} = toRefs(props)  
  
const timestamp = ref(`tMapId${new Date().getTime()}`)  
  
const initMap = (latValue:string, lngValue:string, addressValue:string)=>{  
  
// 定义地图中心点坐标  
const center = new TMap.LatLng(latValue, lngValue);  
// 初始化地图  
const map = new TMap.Map(document.getElementById(timestamp.value), {  
zoom: 17, // 设置地图缩放  
center: new TMap.LatLng(latValue, lngValue), // 设置地图中心点坐标,  
pitch: 0, // 俯仰度  
rotation: 0, // 旋转角度  
});  
  
// MultiMarker文档地址:https://lbs.qq.com/webApi/javascriptGL/glDoc/glDocMarker  
const marker = new TMap.MultiMarker({  
map,  
styles: {  
// 点标记样式  
marker: new TMap.MarkerStyle({  
width: 20, // 样式宽  
height: 30, // 样式高  
anchor: { x: 10, y: 30 }, // 描点位置  
}),  
},  
geometries: [  
// 点标记数据数组  
{  
// 标记位置(纬度,经度,高度)  
position: center,  
id: 'marker',  
},  
],  
});  
  
  
// 初始化label  
const label = new TMap.MultiLabel({  
id: 'label-layer',  
map, // 设置折线图层显示到哪个地图实例中  
// 文字标记样式  
styles: {  
'label': new TMap.LabelStyle({  
'offset': { x: 0, y: -65 }, // 文字偏移属性单位为像素  
'padding': '8px 15px',  
  
'borderRadius': 3,  
'borderWidth': 1,  
'borderColor': '#d6e1fa',  
  
'color': '#3777FF', // 颜色属性  
'size': 14, // 文字大小属性  
'angle': 0, // 文字旋转属性  
'alignment': 'center', // 文字水平对齐属性  
'verticalAlignment': 'middle', // 文字垂直对齐属性  
  
'backgroundColor': '#fff',  
})  
},  
// 文字标记数据  
geometries: [{  
'id': 'label_1', // 点图形数据的标志信息  
'styleId': 'label', // 样式id  
'position': center, // 标注点位置  
'content': addressValue, // 标注文本  
}]  
});  
}  
  
// watch函数监听props.playlist的值  
watch(() => props.lng, (a, pre) => {  
if(pre) initMap(lng.value, lat.value, address?.value)  
},{immediate:true}) // immediate:true,让watch立即执行回调打印值  
  
  
onMounted(()=>{  
if(lng.value && lat.value){  
initMap(lat.value,lng.value, address?.value)  
}
})  
  
  
</script>  
  
<style scoped lang='stylus'>  
.tcMapBase{  
width:100%  
height:300px  
}  
</style>

根据IP获取当前位置

import utilTool from '@/utils/tool'  
  
const nowPosition = ref('')  
utilTool.getCurLocation((address:string)=>{  
nowPosition.value= address  
})


// tool.ts
const getCurLocation = (cb:Function) => {  
const geolocation = new qq.maps.Geolocation();  
  
const options = {timeout: 9000};  
let positionNum = 0;  
  
  
function showPosition(position:object) {  
positionNum ++;  
  
let str = ''  
if(position.province && position.city && position.district){  
str = `${position?.province}·${position?.city}·${position?.district}`  
}else if(position.province && position.city){  
str = `${position?.province}·${position?.city}`  
}  
cb(str, position)  
// {  
// "module": "geolocation",  
// "type": "h5",  
// "adcode": "620123",  
// "nation": "中国",  
// "province": "甘肃省",  
// "city": "兰州市",  
// "district": "榆中县",  
// "addr": "榆中县夏官营镇潘家庄",  
// "lat": 35.861447,  
// "lng": 104.198068,  
// "accuracy": 1804475  
// }  
};  
  
function showErr() {  
if(positionNum<20){  
positionNum ++;  
}  
console.log('腾讯地图,定位失败:', positionNum);  
// eslint-disable-next-line no-use-before-define  
};  
  
function getIpLocFn(){  
geolocation.getIpLocation(showPosition, showErr)  
}  
  
// 详细定位  
// geolocation.getLocation(showPosition, showErr, options);  
  
// 详细定位一直超时,使用根据IP获取定位方法
geolocation.getIpLocation(showPosition, showErr)  
}  
export default {  
getCurLocation  
}

基于腾讯地图点击以及搜索选择目标地址

// 业务页面
<gao-de-view v-if='choseMap' :now-position="nowPosition" @handle-plans='handlePlans' />

import utilTool from '@/utils/tool'  

// 有值时转true
const choseMap = ref(false)

const nowPosition = ref({})  
utilTool.getCurLocation((address:string, option:object)=>{  
console.log('nowPosition.value= option::', option);  
nowPosition.value= option  
})

// 业务页面回填
const handlePlans = (positionDic: any) => {  
console.log('positionDic')  
choseMap.value = false  
diaformModel.ecc017 = positionDic.address  
diaformModel.gpsLon = positionDic.lng  
diaformModel.gpsLat = positionDic.lat  
}


// gaoDeView.vue
<template>  
<div class="mapView">  
<div v-if="!positionInfo.showSearch" class="flx-align-center mb-10">  
<el-input id="address" v-model="positionInfo.address" class="address mr-20" placeholder="请输入地址"></el-input>  
<el-button type="primary" @click="searchByKeyword">查询</el-button>  
<el-button type="primary" :disabled="disabled" @click="saveAddress">保存</el-button>  
</div>  
<div :id="timestamp" class="tcMapBase"></div>  
</div>  
</template>  
<!-- 使用方法 <gao-de-view lng="121.153576213123" lat="31.287459213123" address="杭州市西湖区人才大市场ss" @handlePlans="handlePlan"></gao-de-view>-->  
  
<script lang="ts" setup >  
import { onMounted, ref,nextTick, toRefs } from "vue";  
  
const props = defineProps({  
lat: {  
type: String,  
default: ''  
},  
lng: {  
type: String,  
default: ''  
},  
address: {  
type: String,  
default: '测试地址'  
},  
showSearch:{  
type: Boolean,  
default: false  
},  
nowPosition: {  
type: Object,  
default (){  
return {}  
}  
}  
})  
  
const {lng, lat, address, nowPosition} = toRefs(props)  
  
const disabled = ref(true)  
const positionInfo = ref({  
lat:'',  
lng:'',  
address:'测试地址',  
showSearch:false  
})  
  
const emit = defineEmits(['handlePlans'])  
const saveAddress = () => {  
emit('handlePlans', positionInfo.value)  
};  
  
  
const timestamp = ref(`tMapId${new Date().getTime()}`)  
let map = <any>null  
let center = <any>null  
  
// 初始化marker点  
let marker = <any>null  
const addMarker = (mkCenter:any)=>{  
// MultiMarker文档地址:https://lbs.qq.com/webApi/javascriptGL/glDoc/glDocMarker  
marker = new TMap.MultiMarker({  
map,  
styles: {  
// 点标记样式  
marker: new TMap.MarkerStyle({  
width: 20, // 样式宽  
height: 30, // 样式高  
anchor: { x: 10, y: 30 }, // 描点位置  
}),  
},  
geometries: [  
// 点标记数据数组  
{  
// 标记位置(纬度,经度,高度)  
position: mkCenter,  
id: 'marker',  
},  
],  
});  
}  
  
// 初始化label  
let labelTS = <any>null  
const addLabel = (center:any, addressValue:string)=>{  
labelTS = new TMap.MultiLabel({  
id: 'label-layer',  
map, // 设置折线图层显示到哪个地图实例中  
// 文字标记样式  
styles: {  
'label': new TMap.LabelStyle({  
'offset': { x: 0, y: -65 }, // 文字偏移属性单位为像素  
'padding': '8px 15px',  
  
'borderRadius': 3,  
'borderWidth': 1,  
'borderColor': '#d6e1fa',  
  
'color': '#3777FF', // 颜色属性  
'size': 14, // 文字大小属性  
'angle': 0, // 文字旋转属性  
'alignment': 'center', // 文字水平对齐属性  
'verticalAlignment': 'middle', // 文字垂直对齐属性  
  
'backgroundColor': '#fff',  
})  
},  
// 文字标记数据  
geometries: [{  
'id': 'label_1', // 点图形数据的标志信息  
'styleId': 'label', // 样式id  
'position': center, // 标注点位置  
'content': addressValue, // 标注文本  
}]  
});  
}  
  
// 移除marker标点和 label文本  
function removeMarker() {  
if (marker) {  
marker.setMap(null);  
marker = null;  
}  
  
if(labelTS){  
labelTS.setMap(null)  
labelTS = null  
}  
}  
  
  
let infoWindow = <any>null  
const initMap = (latValue:string, lngValue:string, addressValue:string)=> {  
// console.log(' lngValue:', lngValue, ' latValue:', latValue, ' addressValue:', addressValue);  
  
// 定义地图中心点坐标  
center = new TMap.LatLng(Number(latValue), Number(lngValue));  
// 初始化地图  
map = new TMap.Map(document.getElementById(timestamp.value), {  
zoom: 12, // 设置地图缩放  
center, // 设置地图中心点坐标,  
});  
  
// // 创建信息窗  
infoWindow = new TMap.InfoWindow({  
map,  
position: map.getCenter()  
}).close();  
  
map.on('click', (evt:any) => {  
// 获取click事件返回的poi信息  
const { poi } = evt;  
if (poi) {  
// console.log('拾取到的地址详细poi', poi);  
positionInfo.value.lat = poi.latLng.lat  
positionInfo.value.lng = poi.latLng.lng  
positionInfo.value.address = poi.name  
  
disabled.value= false  
  
// eslint-disable-next-line no-use-before-define  
removeMarker()  
// 拾取到POI  
infoWindow.setContent(poi.name).setPosition(poi.latLng).open();  
} else {  
// 没有拾取到POI  
infoWindow.close();  
}  
});  
  
addMarker(center)  
addLabel(center, addressValue)  
}  
  
const suggest = new TMap.service.Suggestion({  
// 新建一个关键字输入提示类  
pageSize: 10, // 返回结果每页条目数  
region: props.nowPosition.city || '全国', // 限制城市范围  
regionFix: true, // 搜索无结果时是否固定在当前城市  
});  
  
const searchByKeyword = () => {  
// 关键字搜索功能  
suggest  
.getSuggestions({  
keyword: positionInfo.value.address,  
location: map.getCenter(),  
})  
.then((result:any) => {  
if(result.data?.length){  
// console.log('result.data[0]:', result.data[0]);  
// console.log('拾取到的地址详细poi', poi);  
removeMarker()  
  
const info = result.data[0]  
positionInfo.value.lat = info.location.lat  
positionInfo.value.lng = info.location.lng  
positionInfo.value.address = info.address  
  
map.setCenter(new TMap.LatLng(info.location.lat, info.location.lng));  
infoWindow.setContent(`<h3>${info.title}</h3><p>${info.address}</p>`).setPosition(info.location).open();  
disabled.value= false  
}  
});  
}  
  
  
onMounted(async () => {  
await nextTick();  
  
positionInfo.value.address = props.address  
positionInfo.value.showSearch = props.showSearch  
// console.log('nowPosition', nowPosition?.value);  
  
// 地图坐标初始化  
if(lng.value && lat.value){  
positionInfo.value.lat = lat.value  
positionInfo.value.lng = lng.value  
}else if(nowPosition.value.lng && nowPosition.value.lat){  
positionInfo.value.lng = nowPosition.value.lng  
positionInfo.value.lat = nowPosition.value.lat  
}  
  
// console.log('地图坐标 onMounted >>:', positionInfo.value.lat, positionInfo.value.lng);  
if(positionInfo.value.lat && positionInfo.value.lng){  
initMap(positionInfo.value.lat, positionInfo.value.lng, address?.value)  
}  
});  
</script>  
  
<style scoped lang='stylus'>  
.mapView{  
background: white;  
padding: 16px;  
border-radius: 10px;  
  
.tcMapBase{  
width:100%  
height:450px  
}  
}  
  
.flx-align-center{  
display: flex;  
margin-bottom: 16px;  
.address {  
width: 80%;  
margin-right: 16px;  
}  
}  
  
</style>  
<style scoped lang='stylus'>  
:deep(.el-input){  
height: 36px;  
}  
:deep(.el-button--primary){  
height: 36px;  
}  
</style>

指南:lbs.qq.com/service/web… 开发文档:lbs.qq.com/Vis/JUEAPI/… 地图JavaScript API GL:lbs.qq.com/webDemoCent… 地图Raydata Real:lbs.qq.com/webDemoCent…