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。 见下图:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值