vue3?騰訊地圖設(shè)置簽到范圍并獲取經(jīng)緯度的實現(xiàn)代碼
更新時間:2024年04月30日 12:11:16 作者:NZD-Target
本文給大家介紹vue3?騰訊地圖設(shè)置簽到范圍并獲取經(jīng)緯度的實現(xiàn)代碼,本文通過示例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
一.使用說明
- 先騰訊地圖注冊獲取一個密鑰;
- 在項目的開始文件index.html頭部引入script鏈接;
<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&libraries=service&key=你的密鑰"></script>
在項目中調(diào)用自定義組件
二.自定義組件
1.此組件取名MapRadiusSetting.vue
<template>
<div class="content">
<div :id="`mapContent-${eleUuid}`"></div>
<div class="iptContent">
<el-form ref="formRef" :inline="true" :model="state.map" :rules="props.required?state.rules:{}">
<el-form-item label="名稱地點:" prop="address" style="width:100%">
<el-input v-model="state.map.address" maxlength="100" show-word-limit></el-input>
</el-form-item>
<el-form-item label="簽到范圍:" prop="radius">
<el-input-number v-model="state.map.radius" :min="50" :max="9999" :precision="0" :step="1" @change="handleChange" />
</el-form-item>
<div id="location"></div>
</el-form>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'mapRadiusSetting',
})
</script>
<script lang="ts" setup>
import { reactive, ref, unref, onMounted, nextTick ,watch} from 'vue'
import { ElForm, ElMessage, ElMessageBox } from 'element-plus'
import { uuid } from "vue-uuid";
const props = defineProps({
map:{
type: Object,
default: {},
},
required:{
type:Boolean,
default:false
}
})
const eleUuid = ref('')
const formRef = ref(ElForm)
const rangeDistance = (rule: any, value: any, callback: any) => {
if (!value) {
callback(new Error('必填'))
} else if (value && !/^[1-9]\d{0,3}$/.test(value)) {
callback(new Error('請輸入四位以內(nèi)正整數(shù)'))
} else {
callback()
}
}
const state:any = reactive({
map: {
latitude: '',
longitude: '',
radius: 500,
address:'',
uuid: '',
},
rules: {
address: [{ required: true, message: '請輸入', trigger: ['change','blur'] }],
radius: [{ required: true, validator: rangeDistance, trigger: 'change' }],
},
})
var TMap = (window as any).TMap // 引入地圖
var randerCircle:any = {}
var randerMap:any = {}
var markerLayer:any = {}
var geocoderTools:any = {}; // 新建一個正逆地址解析類
const initMap = (mapData: any) => {
let center = new TMap.LatLng(mapData.latitude, mapData.longitude)
//初始化地圖
randerMap = new TMap.Map(`mapContent-${eleUuid.value}`, {
rotation: 0, //設(shè)置地圖旋轉(zhuǎn)角度
pitch: 0, //設(shè)置俯仰角度(0~45)
zoom: 14, //設(shè)置地圖縮放級別
center: center, //設(shè)置地圖中心點坐標
})
geocoderTools = new TMap.service.Geocoder();
//畫圖圓
randerCircle = new TMap.MultiCircle({
map:randerMap,
styles: { // 設(shè)置圓形樣式
'circle': new TMap.CircleStyle({
'color': 'rgba(41,91,255,0.16)',
'showBorder': true,
'borderColor': 'rgba(41,91,255,1)',
'borderWidth': 2,
}),
},
geometries: [{
styleId: 'circle',
center: center,
radius: state.map.radius,
}],
});
//創(chuàng)建并初始化marker
markerLayer = new TMap.MultiMarker({
id: 'marker-layer',
map: randerMap,
//文字標記數(shù)據(jù)
geometries: [
{
id: mapData.uuid,
position: new TMap.LatLng(mapData.latitude, mapData.longitude),
},
],
})
randerMap.on('click', (evt: any)=> {
const lat = evt.latLng.getLat().toFixed(6)
const lng = evt.latLng.getLng().toFixed(6)
state.map.latitude = lat
state.map.longitude = lng
//地圖移到中間
const center2 = new TMap.LatLng(state.map.latitude, state.map.longitude)
// randerMap.setCenter(center2);
//更新或新增標記點
if (mapData.longitude && mapData.latitude) {
markerLayer.setGeometries([])
markerLayer.updateGeometries({
id: mapData.uuid,
position: new TMap.LatLng(lat, lng),
})
} else {
markerLayer.add({
position: evt.latLng,
})
}
//重新畫圈
randerCircle.setGeometries([
{
center: new TMap.LatLng(state.map.latitude, state.map.longitude),
radius: state.map.radius,
id: mapData.uuid,
position: new TMap.LatLng(state.map.latitude, state.map.longitude),
}
])
//獲取地址對應的文字
randerLocationToAddressMap(state.map.latitude, state.map.longitude);
})
}
//范圍變化
const handleChange = () => {
if(state.map.latitude && state.map.longitude && state.map.radius && randerCircle){
//重新畫圈
randerCircle.setGeometries([
{
center: new TMap.LatLng(state.map.latitude, state.map.longitude),
radius: state.map.radius,
id: state.map.uuid,
position: new TMap.LatLng(state.map.latitude, state.map.longitude),
}
])
}
}
//輸入文字轉(zhuǎn)化成坐標,重新渲染
const randerAddressToLocationMap = () => {
// markerLayer.setGeometries([]);
// 將給定的地址轉(zhuǎn)換為坐標位置
geocoderTools
.getLocation({ address: state.map.address })
.then((result:any) => {
console.log("獲取的坐標是啥",result.result.location,state.map.address);
state.map.latitude = result.result.location.lat
state.map.longitude = result.result.location.lng
//地圖移到中間
const center2 = new TMap.LatLng(state.map.latitude, state.map.longitude)
randerMap.setCenter(center2);
//更新或新增標記點
if (state.map.longitude && state.map.longitude) {
markerLayer.updateGeometries({
id: state.map.uuid,
position: new TMap.LatLng(state.map.latitude, state.map.longitude),
})
} else {
markerLayer.add({
position: new TMap.LatLng(state.map.latitude, state.map.longitude),
})
}
//重新畫圈
randerCircle.setGeometries([
{
center: new TMap.LatLng(state.map.latitude, state.map.longitude),
radius: state.map.radius,
id: state.map.uuid,
position: new TMap.LatLng(state.map.latitude, state.map.longitude),
}
])
// document.getElementById(
// 'location'
// )!.innerHTML = result.result.location.toString();
// 顯示坐標數(shù)值
console.log("變化的值",result);
});
}
//將坐標轉(zhuǎn)化成文字
const randerLocationToAddressMap = (latitude:any,longitude:any) => {
var location = new TMap.LatLng(latitude, longitude);
geocoderTools
.getAddress({ location: location }) // 將給定的坐標位置轉(zhuǎn)換為地址
.then((result:any) => {
// 顯示搜索到的地址
console.log("result",result);
if(result.result && result.result.address) state.map.address = result.result.address
});
}
//提交驗證
const submitForm = (callback:any) => {
const form = unref(formRef)
form.validate((valid: any) => {
if (valid) {
console.log(state.map)
if(callback)callback(state.map)
}
})
}
defineExpose({submitForm})
// 關(guān)閉彈窗 清空地圖容器 刷新坐標接口
const handleClose = () => {
(document.getElementById(`mapContent-${eleUuid.value}`) as any).innerHTML = ''
// formRef.value.resetFields() //不起效
}
watch(()=>props.map,()=>{
if(props.map && props.map.uuid){
// eleUuid.value = props.map.uuid
state.map = Object.assign({},state.map,props.map)
handleClose()
nextTick(() => {
initMap(state.map)
})
}
})
onMounted(() => {
eleUuid.value = uuid.v4().replace(/-/g, '');
state.map = {
// 默認值為成都市
latitude: '30.633',
longitude: '104.077',
radius: 50,
uuid: '1',//必須要有值,否則都是新增
address:''
}
if(props.map && props.map.uuid) state.map = Object.assign({},state.map,props.map)
// handleClose()
nextTick(() => {
initMap(state.map)
})
})
</script>
<style lang="scss" scoped>
:deep(.el-dialog) {
.el-dialog__header {
border-bottom: 1px solid #eef5f9;
padding-bottom: 20px;
}
}
#mapContent {
/*地圖(容器)顯示大小*/
width: 100%;
height: 400px;
margin-top: 10px;
cursor: url(https://mapapi.qq.com/web/lbs/static/lbs_home/icon/point1.ico) 12.5 12.5, crosshair;
:deep(a) {
img {
display: none !important;
}
}
:deep(.logo-text) {
display: none !important;
}
:deep(.tmap-scale-control) {
display: none;
}
}
.iptContent {
margin-top: 10px;
.btn {
text-align: right;
border-top: 1px solid #eef5f9;
padding-top: 20px;
button {
width: 100px;
:deep(.el-form-item--small.el-form-item) {
margin-bottom: 0;
}
}
}
}
</style>2.使用
<MapRadiusSetting :map="state.formData" ref="mapRadiusSettingRef" required :key="refreshKey"/>
import MapRadiusSetting from '@/你的自定義組件路徑/components/MapRadiusSetting.vue'
const mapRadiusSettingRef:any = ref({})
//提交觸發(fā)驗證
const submit = ()=>{
mapRadiusSettingRef.value.submitForm((res:any)=>{
//調(diào)用你那邊后端接口,保存經(jīng)緯度 地址 簽到范圍等
//如果res.uuid == '1'說明是新增 ,等于那邊的一個uuid,那么是修改
})
}// 數(shù)據(jù)結(jié)構(gòu)要求
state.formData = {
// 默認值為成都市
latitude: '30.633',
longitude: '104.077',
radius: 50,
uuid: '1',//必須要有值,否則都是新增
address:''
}三.效果

四.計算兩個經(jīng)緯度的距離方法
//地理位置經(jīng)緯度距離
const calculateDistance = (lat1: any, lon1: any, lat2: any, lon2: any, setDistance: number) => {
const radians = Math.PI / 180
const R = 6371 // 地球半徑,單位為千米
const deltaLat = (lat2 - lat1) * radians
const deltaLon = (lon2 - lon1) * radians
lat1 = lat1 * radians
lat2 = lat2 * radians
const a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2)
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
const distance = R * c
return parseInt((distance * 1000).toString()) < setDistance
}
//使用 判斷兩個經(jīng)緯度是不是在500米范圍內(nèi) 在范圍內(nèi)就true 不在就是false
console.log(calculateDistance(lat1, lon1, lat2, lon2,500)到此這篇關(guān)于vue3 騰訊地圖設(shè)置簽到范圍并獲取經(jīng)緯度的文章就介紹到這了,更多相關(guān)vue3 騰訊地圖獲取經(jīng)緯度內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue的Eslint配置文件eslintrc.js說明與規(guī)則介紹
最近在跟著視頻敲項目時,代碼提示出現(xiàn)很多奇奇怪怪的錯誤提示,百度了一下是eslintrc.js文件沒有配置相關(guān)命令,ESlint的語法檢測真的令人抓狂,現(xiàn)在總結(jié)一下這些命令的解釋2020-02-02
Vue計算屬性與監(jiān)視屬性實現(xiàn)方法詳解
最近在學習vue,學習中遇到了一些感覺挺重要的知識點,感覺有必要整理下來,這篇文章主要給大家介紹了關(guān)于Vue.js中計算屬性、監(jiān)視屬性的相關(guān)資料,需要的朋友可以參考下2022-08-08
uniapp實現(xiàn)省市區(qū)三級級聯(lián)選擇功能(含地區(qū)json文件)
這篇文章主要給大家介紹了關(guān)于uniapp實現(xiàn)省市區(qū)三級級聯(lián)選擇功能(含地區(qū)json文件)的相關(guān)資料,級級聯(lián)是一種常見的網(wǎng)頁交互設(shè)計,用于省市區(qū)選擇,它的目的是方便用戶在一系列選項中進行選擇,并且確保所選選項的正確性和完整性,需要的朋友可以參考下2024-06-06

