vue 中 使用腾讯地图 (动态引用腾讯地图及使用签名验证)

news2024/11/20 4:23:06

在这里插入图片描述
在这里插入图片描述

在设置定位的时候使用 腾讯地图 选择地址
在 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。 见下图:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1896175.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android的课程学习助手APP-计算机毕业设计源码19307

基于Android的课程学习助手APP 摘 要 在数字化、信息化的时代背景下&#xff0c;移动学习已成为现代教育发展的重要趋势。为了满足广大学生对高效、便捷学习方式的迫切需求&#xff0c;一款基于Android平台的课程学习助手APP应运而生。这款APP巧妙地将先进的信息技术与学习体验…

养老院生活管理系统

摘要 随着全球范围内人口老龄化趋势的日益加剧&#xff0c;养老院作为老年人生活的重要场所&#xff0c;其生活管理问题也显得愈发突出和重要。为了满足养老院在日常生活管理、老人健康监护、服务人员管理等多方面的需求&#xff0c;提高管理效率和服务质量。决定设计并实现了…

模拟5亿年自然进化史,全新蛋白质大模型ESM3诞生!前Meta老将力作LeCun转赞

模拟5亿年自然进化史&#xff0c;全新蛋白质大模型ESM3诞生&#xff01;前Meta老将力作LeCun转赞。 能抗衡AlphaFold 3的生命科学大模型终于出现了。初创公司Evolutionary Scale AI发布了他们最新的98B参数蛋白质语言模型ESM3。不仅支持序列、结构、功能的all-to-all推理&#…

搞了个 WEB 串口终端,简单分享下

每次换电脑总要找各种串口终端软件&#xff0c;很烦。 有的软件要付费&#xff0c;有的软件要注册&#xff0c;很烦。 找到免费的&#xff0c;还得先下载下来&#xff0c;很烦。 开源的软件下载速度不稳定&#xff0c;很烦。 公司电脑有监控还得让 IT 同事来安装&#xff0…

基于FreeRTOS+STM32CubeMX+LCD1602+AD5621(SPI接口)的DAC控制输出Proteus仿真

一、仿真原理图: 二、运行效果: 三、STM32CubeMX配置: 1)、GPIO配置: 2)、freertos配置: 四、软件部分: 1)、main主函数: /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file …

华为ENSP防火墙+路由器+交换机的常规配置

(防火墙区域DHCP基于接口DHCP中继服务器区域有线区域无线区域&#xff09;配置 一、适用场景&#xff1a; 1、普通企业级网络无冗余网络环境&#xff0c;防火墙作为边界安全设备&#xff0c;分trust&#xff08;内部网络信任区域&#xff09;、untrust&#xff08;外部网络非信…

算法思想总结:优先级队列

一、最后一块石头的重量 . - 力扣&#xff08;LeetCode&#xff09; 我们每次都要快速找到前两个最大的石头进行抵消&#xff0c;这个时候用优先级队列&#xff08;建大堆&#xff09;,不断取堆顶元素是最好的&#xff01;每次删除堆顶元素后&#xff0c;可以自动调整&#xf…

前端面试题10(js多位数组变一维数组)

1. 使用concat()和递归 function flatten(arr) {return arr.reduce((acc, val) > Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val), []); }let multiDimArray [[1, 2, [3]], 4]; let flatArray flatten(multiDimArray); console.log(flatArray); // 输…

GTest和Catch2单元测试学习(附Cmake测试代码库)

kevin_CTest CTest 单元测试学习 Gitee库&#xff1a; https://gitee.com/bigearrabbit/kevin_ctest.git 示例多是从网页文章上摘取的&#xff0c;大部分记录在下面&#xff0c;或者源码内。供学习参考。 CTest 学习Catch2 框架 单个文档的测试架构&#xff0c;使用方便&am…

【SQL】已解决:SQL错误(15048): 数据兼容级别有效值为100、110或120

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决SQL错误(15048): 数据兼容级别有效值为100、110或120 在数据库开发和管理过程中&#xff0c;我们经常会遇到各种各样的错误。本文将详细分析SQL错误(15048)的背景、可能原因、…

转型AI产品经理前需要搞懂的9个问题

笔者近10年来一直工作于AI领域技术和产品一线&#xff0c;今天分享9个大家普遍关注却少有人系统回答的问题。 1.下一个10年&#xff0c;AI产业在国内的发展和职业发展的机遇如何&#xff1f; 从四方面看&#xff1a; &#xff08;1&#xff09;技术角度&#xff1a;逐步成熟…

将代码转为Mac窗口风格的图片

前言 在写博客的时候总觉得默认的代码样式不好看&#xff0c;希望用类似Mac窗口那种三个小圆点的风格转成图片贴出来&#xff0c;所以自己动手做了一个。 一、效果展示 二、在线使用 代码图片生成工具&#xff1a;有码高清 三、源码

【Python机器学习】算法链与管道——利用网格搜索选择使用哪个模型

我们可以进一步将GridSearchCV和Pipeline结合起来&#xff1a;还可以搜索管道中正在执行的实际步骤&#xff08;比如用StandardScaler还是用MinMaxScaler&#xff09;。这样会导致更大的搜索空间&#xff0c;应该予以仔细考虑。 尝试所有可能的解决方案&#xff0c;通常并不是…

MySQL—创建查看删除备份恢复数据库

创建数据库 创建数据库 LLF_DB01CREATE DATABASE LLF_DB01删除数据库DROP DATABASE LLF_DB01创建一个使用utf8字符集的数据库并带校对规则的数据库CREATE DATABASE hsp_db03 CHARACTER SET utf8 COLLATE utf8_bin 查看、删除数据库 显示所有的数据库SHOW DATABASES显示数据库…

C++和Python蚂蚁搬食和蚊虫趋光性和浮标机群行为算法神经网络

&#x1f3af;要点 &#x1f3af;机器人群行为配置和C行为实现&#xff1a;&#x1f58a;脚底机器人狭隘空间导航避让障碍物行为 | &#x1f58a;脚底机器人使用摄像头耦合共振&#xff0c;实现同步动作 | &#x1f58a;脚底机器群使用相机&#xff0c;计算彼此间“分子间势能…

opencv实现目标检测功能----20240704

早在 2017 年 8 月,OpenCV 3.3 正式发布,带来了高度改进的“深度神经网络”(dnn)模块。 该模块支持多种深度学习框架,包括 Caffe、TensorFlow 和 Torch/PyTorch。这次我们使用Opencv深度学习的功能实现目标检测的功能,模型选用MobileNetSSD_deploy.caffemodel。 模型加载…

Linux 文件系统以及日志管理

一、inode 与block 1. inode 与block详解 在文件存储硬盘上&#xff0c;硬盘的最小存储单位叫做“扇区”&#xff0c;每个为512字节。 操作系统读取硬盘的时候&#xff0c;不会一个个扇区地读取&#xff0c;这样效率太低&#xff0c;而是一次性连续读取多个扇区,即一次性读取…

传感器标定(一)摄像头内参标定

一、使用ROS进行手动标定安装 1、安装 image-view &usb_cam ⽤于驱动相机 sudo apt-get install ros-melodic-image-view sudo apt-get install ros-melodic-usb-cam2、查看系统视频设备 v4l2- ctl -d /dev/video0 --all 查询所有相机具体的参数包括width和height ls /…

JavaScript原型对象和对象原型、原型继承、原型链

目录 1. 原型对象和对象原型2. 原型继承3. 原型链 1. 原型对象和对象原型 作用: 以前通过构造函数实例化的对象&#xff0c;每个实例化的对象的属性和方法都是独立的&#xff0c;会造成内存浪费。通过prototype对象原型能实现不同实例化对象共享公用的属性和方法&#xff0c;减…