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…