vue3 + 腾讯地图API + 拖拽定位

作为一个前端的新手,没有经过系统学习前端,所有都是一点点找资料实践后摸索出来。文中有写两个暂时无法解决的Bug,希望有人可以不吝赐教。如果有错误,欢迎各位指正。
前提:当前我用的是vue3,在组件中都使用了setup语法糖以及使用typescript,因此在每个组件都用了

<script lang="ts" setup>

首先,在腾讯官网上申请API。
https://lbs.qq.com/dev/console/quota/mine

并且在index.html加入引入JS文件接入腾讯地图API的语句,语句中需要使用KEY。

<script src="https://map.qq.com/api/gljs?v=2.exp&key="在腾讯官网申请的KEY"></script>

引入腾讯地图
现在新建一个子组件,在里面写入(注意这里ID可以自己修改,但是下面js部分需要与此处相同)

<template>
  <div id="QQMap" />
</template>
<script lang="ts" setup>

</script>
<style>
</style>

现在开始写script中地图新建部分:
导入需要的库后,首先我先保存了自己的key方便后续使用。
之后的TMap是需要的,第一次按照官网写,一直找不到这个TMap,我在网上找很多资料中最终发现这句话,加入后后面就能跑了,似乎是因为外部引入script后都在window下了。
最后新建一个变量存入拖动后经纬度以及后续初始化的地图和图层。

import { onMounted, reactive, watch } from "vue";
import $ from "jquery";
const key = "";
const TMap = (window as any).TMap;
const dataMap = reactive({
  map: "" as any,
  markerLayer: "" as any,
  latitude: 0 as number, //纬度
  lngitude: 0 as number, //经度
});

在这里写入几个函数。
第一个是获取非精确地址的,通过IP地址获取当前精确到市级位置,详细介绍看官网链接:https://lbs.qq.com/service/webService/webServiceGuide/webServiceIp

// 异步获得位置
// 通过终端设备IP地址获取其当前所在地理位置,精确到市级
// 常用于初始化用户城市等非精确定位场景。
const getNowLngAndLat = $.ajax({
  type: 'get',
  url: 'https://apis.map.qq.com/ws/location/v1/ip',
  data: {
    key: key,
    output: 'jsonp',
  },
  dataType: 'jsonp',
  success: function (res) {
    // console.log(res)
    dataMap.latitude = res.result.location.lat;
    dataMap.lngitude = res.result.location.lng;
  },
  fail: function () {
  }
})

第二个是初始化地图,这里获取的ID需要与之前写的ID相同。
(小疑惑:在子组件中没问题,但是移到父组件初始化就会报错:
Cannot read properties of null (reading ‘id’),按照网上说法加入window.onlaod仍然不行,至今未解决)

const init = () => {
  let center = new TMap.LatLng(dataMap.latitude, dataMap.lngitude);
  dataMap.map = new TMap.Map(document.getElementById("QQMap"), {
    center: center, //设置地图中心点坐标
    zoom: 17.2, //设置地图缩放级别
  });
};

第三个就是删除无用信息了,腾讯地图有他的logo和罗盘等,我不想要,因此写入函数去除。中间如果修改了ID也需要修改

// 去除无用信息
const deleteSomeInfo = () => {
  // 腾讯地图去除logo
  var logo = document.querySelector(
    "#QQMap > div > div:nth-child(2) > div:nth-child(1) > div:nth-child(2)"
  ) as Element;
  logo.setAttribute("style", "display: none;");
  // 腾讯地图去除logo文字
  var logoText = document.getElementsByClassName("logo-text");
  logoText[0].setAttribute("style", "display: none;");
  // 腾讯地图去除罗盘
  var logoCompass = document.getElementsByClassName("rotate-circle");
  logoCompass[0].setAttribute("style", "display: none;");
  // 获取缩放控件实例
  let control = dataMap.map.getControl(TMap.constants.DEFAULT_CONTROL_ID.ZOOM);
  // 设置控件在右下角
  control.setPosition(TMap.constants.CONTROL_POSITION.BOTTOM_RIGHT);
  // 缩放控件显示缩放级别
  control.setNumVisible(true);
};

最后一个添加图层我们先暂时不说,先说我们调用时顺序,这里首先调用获取当前粗略位置函数,获取后进入初始化,初始化使用当前经纬度,之后删除信息,最后就是我们加入图层函数。

onMounted(() => {
  $.when(getNowLngAndLat).done(function () {
    init();
    deleteSomeInfo();
    addMarkerLayer();
  });
});

为什么这里的加入图层最后讲呢,因为Bug就是这里出现的,而且暂时不知如何解决
加入图层本来是正常,首先加入点,并且获取地图中心位置,之后添加图层,并且监控地图是否平移,一旦移动,修改经纬度并且更新标记点。之后本想使用官网给的updateGeometries函数,但是一直报错,如下:
Uncaught DOMException: Failed to execute ‘postMessage’ on ‘Worker’: # could not be cloned.
在这里插入图片描述
新手找了很多资料还是没找到解决办法,只能曲线救国,先删除再加入,但是这样就会导致标记点一直闪烁。算是最难受的一个bug了。

const addMarkerLayer = () => {
  // 加入标记点
  var markerGeo = {
    id: "center",
    position: dataMap.map.getCenter(),
  };

  // 创建一个位于地图中心点的marker
  dataMap.markerLayer = new TMap.MultiMarker({
    map: dataMap.map, //指定地图容器
    geometries: [markerGeo], //点标记数据数组
  });
  //监听地图平移,panstart开始平移,panend平移结束
  dataMap.map.on("pan", function () {
    markerGeo.position = dataMap.map.getCenter(); //获取地图中心点
    dataMap.latitude = markerGeo.position.lat;
    dataMap.lngitude = markerGeo.position.lng;
    // dataMap.markerLayer.updateGeometries([markerGeo]); // 报错,只好先删后加
    dataMap.markerLayer.setMap(null); // 或者dataMap.markerLayer.destroy();
    dataMap.markerLayer = new TMap.MultiMarker({
      map: dataMap.map, //指定地图容器
      //点标记数据数组
      geometries: [markerGeo],
    });
  });
};

最后加上两个没有用到的函数吧。
第一个是动态加载的函数,用于尝试的,后面也没有使用他:

// 动态加载script,如果index.html去除script,在这里需要动态加载
function loadScript() {
  var script = document.createElement("script");
  script.type = "text/javascript";
  script.src = "https://map.qq.com/api/gljs?v=1.exp&key=" + key;
  document.body.appendChild(script);
}

第二是飞到某个地方的函数

function easeTo(lng: number, lat: number) {
  // console.log([lat,lng])
  var center = new TMap.LatLng(lat, lng);
  dataMap.latitude = lat;
  dataMap.lngitude = lng;
  dataMap.map.easeTo({ center: center }, { duration: 2000 });//平滑缩放,旋转到指定级别
}

这样就可以在父组件调用该组件即可出现腾讯地图了。效果如下:

第一次写这么长博客,有错误或者知道bug欢迎各位大佬斧正。

Logo

前往低代码交流专区

更多推荐