vue3?騰訊地圖設(shè)置簽到范圍并獲取經(jīng)緯度的實(shí)現(xiàn)代碼
一.使用說明
- 先騰訊地圖注冊獲取一個(gè)密鑰;
- 在項(xiàng)目的開始文件index.html頭部引入script鏈接;
<script charset="utf-8" src="https://map.qq.com/api/gljs?v=1.exp&libraries=service&key=你的密鑰"></script>
在項(xiàng)目中調(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="名稱地點(diǎn):" 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 = {}; // 新建一個(gè)正逆地址解析類 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è)置地圖中心點(diǎn)坐標(biāo) }) 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, //文字標(biāo)記數(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); //更新或新增標(biāo)記點(diǎn) 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), } ]) //獲取地址對應(yīng)的文字 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)化成坐標(biāo),重新渲染 const randerAddressToLocationMap = () => { // markerLayer.setGeometries([]); // 將給定的地址轉(zhuǎn)換為坐標(biāo)位置 geocoderTools .getLocation({ address: state.map.address }) .then((result:any) => { console.log("獲取的坐標(biāo)是啥",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); //更新或新增標(biāo)記點(diǎn) 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(); // 顯示坐標(biāo)數(shù)值 console.log("變化的值",result); }); } //將坐標(biāo)轉(zhuǎn)化成文字 const randerLocationToAddressMap = (latitude:any,longitude:any) => { var location = new TMap.LatLng(latitude, longitude); geocoderTools .getAddress({ location: location }) // 將給定的坐標(biāo)位置轉(zhuǎn)換為地址 .then((result:any) => { // 顯示搜索到的地址 console.log("result",result); if(result.result && result.result.address) state.map.address = result.result.address }); } //提交驗(yàn)證 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)閉彈窗 清空地圖容器 刷新坐標(biāo)接口 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 = { // 默認(rèn)值為成都市 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ā)驗(yàn)證 const submit = ()=>{ mapRadiusSettingRef.value.submitForm((res:any)=>{ //調(diào)用你那邊后端接口,保存經(jīng)緯度 地址 簽到范圍等 //如果res.uuid == '1'說明是新增 ,等于那邊的一個(gè)uuid,那么是修改 }) }
// 數(shù)據(jù)結(jié)構(gòu)要求 state.formData = { // 默認(rèn)值為成都市 latitude: '30.633', longitude: '104.077', radius: 50, uuid: '1',//必須要有值,否則都是新增 address:'' }
三.效果
四.計(jì)算兩個(gè)經(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 } //使用 判斷兩個(gè)經(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àng)目時(shí),代碼提示出現(xiàn)很多奇奇怪怪的錯(cuò)誤提示,百度了一下是eslintrc.js文件沒有配置相關(guān)命令,ESlint的語法檢測真的令人抓狂,現(xiàn)在總結(jié)一下這些命令的解釋2020-02-02element日期組件實(shí)現(xiàn)只能選擇小時(shí)或分鐘
本文主要介紹了element日期組件實(shí)現(xiàn)只能選擇小時(shí)或分鐘,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01vue2.0項(xiàng)目集成Cesium的實(shí)現(xiàn)方法
這篇文章主要介紹了vue2.0項(xiàng)目集成Cesium的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Vue計(jì)算屬性與監(jiān)視屬性實(shí)現(xiàn)方法詳解
最近在學(xué)習(xí)vue,學(xué)習(xí)中遇到了一些感覺挺重要的知識點(diǎn),感覺有必要整理下來,這篇文章主要給大家介紹了關(guān)于Vue.js中計(jì)算屬性、監(jiān)視屬性的相關(guān)資料,需要的朋友可以參考下2022-08-08vue路由前進(jìn)后退動畫效果的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue路由前進(jìn)后退動畫效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-12-12uniapp實(shí)現(xiàn)省市區(qū)三級級聯(lián)選擇功能(含地區(qū)json文件)
這篇文章主要給大家介紹了關(guān)于uniapp實(shí)現(xiàn)省市區(qū)三級級聯(lián)選擇功能(含地區(qū)json文件)的相關(guān)資料,級級聯(lián)是一種常見的網(wǎng)頁交互設(shè)計(jì),用于省市區(qū)選擇,它的目的是方便用戶在一系列選項(xiàng)中進(jìn)行選擇,并且確保所選選項(xiàng)的正確性和完整性,需要的朋友可以參考下2024-06-06