vue 中 使用腾讯地图 (动态引用腾讯地图及使用签名验证)
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
免费下载资源
·
在设置定位的时候使用 腾讯地图 选择地址
在 mounted中引入腾讯地图:
this.website.mapKey 为地图的 key
// 异步加载腾讯地图API
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://map.qq.com/api/js?v=2.exp&key='+this.website.mapKey+'&callback=init';
document.body.appendChild(script);
// 回调函数,初始化地图
window.init = () => {
this.initMap();
this.$nextTick(()=>{
if(this.map){
// // 监听中心点变化事件,更新marker的位置
this.listener=qq.maps.event.addListener(this.map, 'dragend', ()=>this.centerChanged());
}
})
};
在 destroyed 卸载
destroyed(){
let scripts = document.querySelectorAll('script');
// 遍历所有找到的<script>元素并移除它们
scripts.forEach((script)=> {
let src=script.getAttribute('src');
if(src&&src.indexOf('qq')>=0){
script.parentNode.removeChild(script);
}
});
qq.maps.event.removeListener(this.listener)
},
弹框组件代码为:
<template>
<el-dialog title="设置定位"
:visible.sync="dialogVisible"
width="900px"
:before-close="handleClose"
:modal-append-to-body="true"
:append-to-body="true"
:close-on-click-modal="false"
v-dialogdrag
class="common-dialog">
<div class="clearfix">
<div class="pull-left near-box">
<el-input v-model="keyword" @change="changeKeyword">
<el-button slot="append" icon="el-icon-search" @click="searchNear"></el-button>
</el-input>
<ul class="location-list">
<li v-for="(item,index) in nearList" :key="index" :class="selectedIndex==index?'location-active':''">
<div @click="handleSelect(item,index)">
<div class="location-title">{{item.title}}</div>
<span class="location-address">{{item.address}}</span>
</div>
</li>
</ul>
</div>
<div class="pull-right map-box">
<div id="container"></div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="submitAction">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
import {mapGetters} from "vuex";
import {getAddressByLat,searchByKeyword} from '@/api/address'
export default {
props:{
form:{
type: Object
}
},
data(){
return {
selectedIndex:'',
keyword: '山东省青岛市',
dialogVisible : true,
mapZoom: 15,
pitch: 0,
addressInfo: this.form,
mapCenter: {
adcode: 370203,
city: "青岛市",
district: "市北区",
ip: "111.17.222.181",
lat: 36.08743,
lng: 120.37479,
nation: "中国",
province: "山东省"
},
nearList:[],
map:null,//地图
markerLayer:null,
listener:null
}
},
mounted(){
if(this.form.lat&&this.form.lng){
this.mapCenter={
...this.form,
city:this.form.cityName
};
this.keyword=this.form.provinceName+this.form.cityName+this.form.areaName+this.form.address.substring(0,64)
} else if(this.location.lat){
this.mapCenter = {...this.location};
if(this.location.province&&this.location.city){
this.keyword=(this.location.province+this.location.city).substring(0,64)
}
}
// 异步加载腾讯地图API
const script = document.createElement('script');
script.type = 'text/javascript';
script.id = 'qqMap';
script.name = 'qqMap';
script.src = 'https://map.qq.com/api/js?v=2.exp&key='+this.website.mapKey+'&callback=init';
document.body.appendChild(script);
// 回调函数,初始化地图
window.init = () => {
this.initMap();
this.$nextTick(()=>{
if(this.map){
// // 监听中心点变化事件,更新marker的位置
this.listener=qq.maps.event.addListener(this.map, 'dragend', ()=>this.centerChanged());
}
})
};
},
destroyed(){
let scripts = document.querySelectorAll('script');
// 遍历所有找到的<script>元素并移除它们
scripts.forEach((script)=> {
let src=script.getAttribute('src');
if(src&&src.indexOf('qq')>=0){
script.parentNode.removeChild(script);
}
});
qq.maps.event.removeListener(this.listener)
},
computed: {
...mapGetters(["location"]),
},
methods:{
//初始化地图
initMap(){
let element=document.getElementById('container');
//定义地图中心点坐标
let center=new qq.maps.LatLng(this.mapCenter.lat,this.mapCenter.lng);
//定义map变量,调用 TMap.Map() 构造函数创建地图
this.map = new qq.maps.Map(element, {
pitch: this.pitch,
center: center,//设置地图中心点坐标
zoom:this.mapZoom, //设置地图缩放级别
});
// 创建一个位于地图中心点的marker
this.markerLayer = new qq.maps.Marker({
map: this.map,
position: center
});
if(this.keyword){
this.getAddressByKeyword( this.mapCenter)
}
},
centerChanged(){
this.mapCenter=this.map.getCenter();
this.getLocationByLat()
},
//当前选择
handleSelect(item,index){
this.selectedIndex=index;
this.mapCenter={
...item,
lat:item.location.lat,
lng:item.location.lng,
};
this.map.setCenter(new qq.maps.LatLng(item.location.lat,item.location.lng));
this.markerLayer.setPosition(new qq.maps.LatLng(item.location.lat,item.location.lng))
// this.getLocationByLat()
},
changeKeyword(val){
this.keyword=val;
},
searchNear(){
this.mapCenter={};
this.getAddressByKeyword()
},
getLocationByLat(){
getAddressByLat({
location:`${this.mapCenter.lat},${this.mapCenter.lng}`,
key:this.website.mapKey,
}).then(res=>{
this.keyword=res.result.address;
this.getAddressByKeyword(res.result)
})
},
//根据关键字查找地址列表
//https://lbs.qq.com/service/webService/webServiceGuide/webServiceSuggestion
getAddressByKeyword(latInfo){
let params={
keyword:this.keyword,
region:this.mapCenter.city?this.mapCenter.city:'',
policy:1,
page_size:20,
page_index:1,
address_format:'short',
key:this.website.mapKey,
};
if(this.mapCenter.lat&&this.mapCenter.lat!=-1&&this.mapCenter.lng&&this.mapCenter.lng!=-1){
params.location=`${this.mapCenter.lat},${this.mapCenter.lng}`
}
searchByKeyword(params).then(res=>{
this.nearList=res.data;
let first=res.data&&res.data[0]?res.data[0]:'';
if(first){
this.selectedIndex=0;
if(!params.location){
let lat=first.location.lat;
let lng=first.location.lng;
this.mapCenter={
...first,
lat:lat,
lng:lng
};
this.map.setCenter(new qq.maps.LatLng(lat,lng))
}
} else if(latInfo){
let obj={
...latInfo.ad_info,
...latInfo.location,
address:latInfo.address,
title:latInfo.formatted_addresses&&latInfo.formatted_addresses.recommend?latInfo.formatted_addresses.recommend:latInfo.address
};
this.mapCenter=obj;
this.nearList=[obj];
this.map.setCenter(new qq.maps.LatLng(this.mapCenter.lat,this.mapCenter.lng))
}
this.markerLayer.setPosition(new qq.maps.LatLng(this.mapCenter.lat,this.mapCenter.lng))
})
},
handleClose(){
this.dialogVisible=false;
this.$emit('closeDialog',false)
},
submitAction(){
if(!this.keyword){
this.$message.error('请输入关键字查询/或拖动地图查找');
return false
}
this.$emit('changeMapLocation', this.selectedIndex>=0&&this.nearList[this.selectedIndex]?this.nearList[this.selectedIndex]:this.mapCenter);
this.handleClose()
}
}
}
</script>
<style lang="scss" scoped>
@import "@/styles/variables";
.common-dialog {
/deep/.el-dialog__body{
padding:20px 30px;
}
.el-input__inner{
height:36px;
line-height: 36px;
}
}
.near-box{
width:300px;
height:500px;
}
.map-box{
width:calc(100% - 320px);
height:500px;
margin:0;
padding:0
}
#container{
width:100%;
height:100%;
}
/deep/ .el-input{
min-width: auto;
}
.location-list{
list-style: none;
margin: 10px 0 0;
padding:0;
max-height: 460px;
border:1px solid $color-border-light;
overflow-y: auto;
}
.location-list li{
list-style: none;
padding:5px;
border-bottom:1px solid $color-border-light;
cursor: pointer;
&:last-child{
border-bottom: none;
}
}
.location-list li.location-active{
background-color: $color-primary;
.location-title,.location-address{
color:#fff;
}
}
.location-title{
font-size: 14px;
color:$color-text-dark;
font-weight: bold;
}
.location-address{
font-size: 12px;
color: $color-text-secondary;
transform: scale(0.85);
}
</style>
以逆地址解析为例写法为:
import request from "@/axios";
//逆地址解析
export const getAddressByLat = (params) =>{
return request.jsonp('/ws/geocoder/v1', {
output: "jsonp",
...params
})
}
axios 调用 jsonp 方法
import axios from 'axios';
import {serialize} from '@/util/util';
import {Message} from 'element-ui';
axios.jsonp = function(url,data){
if(!url) throw new Error('接口地址错误')
function sortObjectByKeys(obj) {
return Object.keys(obj)
.sort()
.reduce((sortedObj, key) => {
sortedObj[key] = obj[key];
return sortedObj;
}, {});
}
const callback = 'CALLBACK' + Math.random().toString().substr(9,18)
const time=Date.now();
let newData=sortObjectByKeys({
...data,
callback,
time
});
let sign=md5(`${url}?${serialize(newData)}YOUR_SK`);
const JSONP = document.createElement('script')
JSONP.setAttribute('type','text/javascript')
const headEle = document.getElementsByTagName('head')[0];
JSONP.src = `https://apis.map.qq.com${url}?${serialize(newData)}&sig=${sign}`;
return new Promise( (resolve) => {
window[callback] = r => {
if(r.status!='0'){
Message({
message: r.message,
type: 'warning'
});
}
resolve(r)
headEle.removeChild(JSONP)
delete window[callback]
}
headEle.appendChild(JSONP)
})
}
export default axios;
YOUR_SK为腾讯地图签名验证时SK。 见下图:
GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891
Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
更多推荐
已为社区贡献1条内容
所有评论(0)