一、前言
之前做过一个 高德地图 接入,功能基本一致,本文使用腾讯地图完成了相关功能,比高德地图多了一个区域的绘制功能。本文除了功能使用外还会讲解一些两者的异同。
在文末会有该 demo 的项目地址,希望大家看完可以多多点赞👍收藏⭐一下。
二、准备工作
1、参考博客以及相关地址
腾讯位置服务:平台地址
【Uniapp】高德地图的接入、定位、自定义标点与信息窗体使用:文档地址
2、注册腾讯位置服务账号
我们需要先在腾讯位置服务注册一个账号,以申请获取 key 等权限信息。注册流程很简单,就不赘述了,获取成功后点击此处:
![image-20231122095253546](https://img-blog.csdnimg.cn/img_convert/cc2e6c51042fa5abe694da4037645636.png)
点击创建新应用,至于里面的内容就是随便填都可以:
![image-20231122095714598](https://img-blog.csdnimg.cn/img_convert/2bb8957f2de2a04faecb462641f56649.png)
点击添加 Key ,创建你的 Key 值,我们后面都需要使用,具体你是哪个开发平台就勾选哪一个:
![image-20231122095948235](https://img-blog.csdnimg.cn/img_convert/90bf1aaac9dfc99ae01db643d580c606.png)
下面是最后生成的 Key。我使用的是动态导入,但是也有人使用的是本地导入下载的SDK,大家可以尝试一下哪个更适合你的开发。
![image-20231122100255895](https://img-blog.csdnimg.cn/img_convert/29d4e8b9eb6a2b69aaaadf698f62ef82.png)
三、导入以及使用
以下内容较多篇幅较长,大家可以根据目录选择阅读,我会结合官方文档以及参考文档详细说明每一个方法的使用以及具体实现,但最好还是按顺序看下去。
1、参考博客与文档以及相关地址
腾讯官方文档:地址
2、导入地图
这个导入方法和高德地图的导入基本一致,定义一个全局的地图实例供我们调用腾讯地图的API。
效果
![image-20231123104436681](https://img-blog.csdnimg.cn/img_convert/984af2e46efef36cb88667ea24aa91c2.png)
代码
let mapObj = null; // 生成组件实例
window.mapInit = function() { // 挂载地图实例
mapObj = new TMap.Map("wrapper", {
center: new TMap.LatLng(22.254515, 113.469689), // 地图初始坐标
zoom: 14, // 缩放等级
mapStyleId: 'style1', // 地图样式
zoomControl: false, // 设置是否启用缩放控件
});
mapObj.on("click", function(evt) { // 地图全局事件
// 这里是通过获取地图点击的位置,将该位置移动至中心点,后面会用上
mapObj.setCenter(new TMap.LatLng(evt.latLng.getLat().toFixed(6), evt.latLng.getLng().toFixed(6)))
})
}
export default {
data() {
return {
key: '00000-00000-00000-00000-00000-00000', // 换你自己的key
}
},
onLoad() {
// #ifdef H5
this.loadScrpit();
// #endif
},
created() {},
methods: {
// 初始化
loadScrpit() { // 挂载js
var script = document.createElement('script');
script.src =
`https://map.qq.com/api/gljs?v=1.exp&key=${this.key}&libraries=visualization&callback=mapInit`;
document.body.appendChild(script);
},
}
}
.content {
position: fixed;
top: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.wrapperBox {
position: relative;
width: 100vw;
height: 100vh;
z-index: 1;
}
#wrapper {
z-index: 20;
width: 120vw;
height: 120vh;
top: -10vh;
left: -10vw;
position: absolute;
}
代码讲解
首先是在 onLoad() 在页面加载阶段内调用动态挂载函数,熟悉原生 JavaScript 的朋友都应该可以明白这是一个创建 标签,并把它插入 body 内的操作。关键是在标签的属性上,我们需要传入 Key 值和回调函数。
📌 此处的回调函数可以取任意名,但需要注意的是在 window.function() 接收函数时需要同名,否则无法成功接收回调函数。
mapObj = new TMap.Map("wrapper", {
center: new TMap.LatLng(Longitude, Latitude), // 地图初始坐标
zoom: 14, // 缩放等级
mapStyleId: 'style1', // 地图样式
zoomControl: false, // 设置是否启用缩放控件
});
在本文中我使用 mapObj 全局存储地图的实例, new TMap.Map('id',Object) 的参数:
id:地图将会渲染在同名 id 的 view 或 div 内。 📍 需要注意的是,如果你想要在地图上自定义一些控件或展示框,最好不在该标签内添加,因为当你定位到一个新的地点时,它将刷新整个地图,你所定义的界面将会全部消失。正确的做法应该是建立一个同级的标签,通过 z-index 属性置于地图的上层。
Object:你可以通过该对象决定你的地图需要哪些图层与初始定位,还有缩放的级数等功能。
center: new TMap.LatLng(22.254515, 113.469689) ,设置中心点的位置; zoom:初始地图的缩放级数,同样也是根据你的业务需求设置就好了; zoomControl:这个控件看个人的业务需求,不关就会是这个效果: ![image-20231123111005663](https://img-blog.csdnimg.cn/img_convert/adf0a6ddc2919afa4f9fe5eaa49cf6c6.png) mapStyleId:style1,这个设置的是地图样式,需要先在腾讯位置服务配置相关的样式文件:
进入该页面选择基础的样式模板(免费),高级模板就需要付费了
![image-20231123142655593](https://img-blog.csdnimg.cn/img_convert/5dceb209458f33d4d152d378e3ddb879.png)
点击绑定相关的样式,这里需要你选择是使用哪个的,然后绑定到key上
![image-20231123143631822](https://img-blog.csdnimg.cn/img_convert/5c7e7a03e315a2e23b6bf651be8e20c7.png)
已绑定的样式就会显示在这个的地方
![image-20231123145736653](https://img-blog.csdnimg.cn/img_convert/ac2b2bdd9e0351ca59504ea2615b9060.png)
鼠标移动上去即可查看对应的样式名,也就是上文对应的 style1:
![image-20231123150012887](https://img-blog.csdnimg.cn/img_convert/d947949301915dec70a0c5e45ba34410.png)
3、点击坐标定位
这里点击和高德的定位不太一样,设置起来相对简单一点,只需要传入坐标点。一般需要和标点一起使用,在下文会再做讲解。
mapObj.setCenter(new TMap.LatLng(Latitude, Longitude))
代码讲解
腾讯地图提供了 setCenter() 方法可供设置中心点,不会像高德一样重置标点和信息窗体,无需重新挂载。
4、自定义标点
自定义标点主要是定义图标的图像以及大小、图片地址等参数。需要注意的是,标点自定义必须在地图实例挂载之后,否则无法定义成功。自定义标点信息成功后再挂载标点,本文使用了多个标点图标,可以根据同样的方法设置,最后实现的就是下图效果。
效果
![image-20231123161603666](https://img-blog.csdnimg.cn/img_convert/05231ebd7827c36c46173fa11ff908d4.png)
代码
let mapObj = null; // 生成地图实例
// ------------------------------ 更新内容1 ----------------------------- //
// 创建多个标点
let agriculture = []; // 生成图标实例1
let property = []; // 生成图标实例2
let construction = []; // 生成图标实例3
let noRented = []; // 生成图标实例4
let marker = []; // 生成标点实例
// ---------------------------------------------------------------------- //
window.mapInit = function() { // 挂载地图实例
mapObj = new TMap.Map("wrapper", {
center: new TMap.LatLng(22.254515, 113.469689), // 地图初始坐标
zoom: 14, // 缩放等级
mapStyleId: 'style1', // 地图样式
zoomControl: false, // 设置是否启用缩放控件
});
mapObj.on("click", function(evt) { // 地图全局事件
mapObj.setCenter(new TMap.LatLng(evt.latLng.getLat().toFixed(6), evt.latLng.getLng().toFixed(6)))
})
}
export default {
data() {
return {
key: 'OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77',
// ------------------------------ 更新内容2 ----------------------------- //
iconItem: [{ // 模拟数据
name: 'agriculture', // 样式类型
src: require("@/static/dot-01.png"), // 图片路径
position: [22.227959, 113.459589], // 标点中心坐标
markerUrl: require("@/static/dot-01.png"), // 标点图片样式
}, {
name: 'property',
src: require("@/static/dot-02.png"),
position: [22.253496, 113.477076],
markerUrl: require("@/static/dot-02.png"),
}, {
name: 'construction',
src: require("@/static/dot-03.png"),
position: [22.237834, 113.463987],
markerUrl: require("@/static/dot-03.png"),
}, {
name: 'noRented',
src: require("@/static/dot-04.png"),
position: [22.253692, 113.498333],
markerUrl: require("@/static/dot-04.png"),
}]
// ---------------------------------------------------------------------- //
}
},
onLoad() {
// #ifdef H5
this.loadScrpit();
// #endif
// ------------------------------ 更新内容3 ----------------------------- //
let time = setInterval(() => { // 等待地图挂载
if (mapObj != null) {
clearInterval(time);
this.setIcon(); // 挂载坐标图片信息
}
}, 100)
// ---------------------------------------------------------------------- //
},
methods: {
// 初始化
loadScrpit() { // 挂载js
var script = document.createElement('script');
script.src =
`https://map.qq.com/api/gljs?v=1.exp&key=${this.key}&libraries=visualization&callback=mapInit`;
document.body.appendChild(script);
},
// ------------------------------ 更新内容4 ----------------------------- //
setIcon() { // 创建标点图标
let that = this;
// 创建 AMap.Icon 实例
agriculture = new TMap.MarkerStyle({
"width": 75, // 定义宽,单位:PX
"height": 90, // 定义高,单位:PX
"src": that.iconItem[0].markerUrl, // 标点图片链接:本地图片
})
property = new TMap.MarkerStyle({
"width": 75,
"height": 90,
"src": that.iconItem[1].markerUrl,
})
construction = new TMap.MarkerStyle({
"width": 75,
"height": 90,
"src": that.iconItem[2].markerUrl,
})
noRented = new TMap.MarkerStyle({
"width": 75,
"height": 90,
"src": that.iconItem[3].markerUrl,
})
this.setMapMarker(); // 调用创建标点
},
setMapMarker() { // 创建标点实例
let geometries = [];
for (let i = 0; i // 点标记数据
"id": i, //点标记唯一标识,后续如果有删除、修改位置等操作,都需要此id
"styleId": this.iconItem[i].name, // 对应标点实例的style的名称
"position": new TMap.LatLng(this.iconItem[i].position[0], this.iconItem[i].position[1]), // 标点的坐标
"properties": { // 自定义属性
"title": this.iconItem[i].name
}
}
geometries.push(obj);
}
marker = new TMap.MultiMarker({ // 构造函数创建标点实例
id: 'marker-layer', // 定义的ID名称
map: mapObj, // 挂载的地图实例
styles: { // 加入标点的样式
"agriculture": agriculture,
"property": property,
"construction": construction,
"noRented": noRented,
},
geometries: geometries // 点标记数据数组
});
},
// ---------------------------------------------------------------------- //
}
}
.content {
position: fixed;
top: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.wrapperBox {
position: relative;
width: 100vw;
height: 100vh;
z-index: 1;
}
#wrapper {
z-index: 20;
width: 120vw;
height: 120vh;
top: -10vh;
left: -10vw;
position: absolute;
}
代码讲解
更新内容1:本地图创建了多个标点样式 agriculture property construction noRented,在创建标点时对应相应的样式。创建 marker 在下文挂载标点实例。
// 创建多个标点
let agriculture = []; // 生成图标实例1
let property = []; // 生成图标实例2
let construction = []; // 生成图标实例3
let noRented = []; // 生成图标实例4
let marker = []; // 生成标点实例
更新内容2:此处为后台返回的模拟数据,有需要可参考该数据。
iconItem: [{ // 模拟数据
name: 'agriculture', // 样式类型
src: require("@/static/dot-01.png"), // 图片路径
position: [22.227959, 113.459589], // 标点中心坐标
markerUrl: require("@/static/dot-01.png"), // 标点图片样式
}]
更新内容3:在 onLoad() 里设置定时器监听地图是否挂载成功,没挂载地图实例前无法挂载标点图片与坐标标点。一旦监听到地图组件挂载便取消对应的定时器监听。
let time = setInterval(() => { // 等待地图挂载
if (mapObj != null) {
clearInterval(time);
this.setIcon(); // 挂载坐标图片信息
}
}, 100)
更新内容4:
setIcon(): 设置自定义标点图片的参数,具体的参数看下面介绍,按照对应的测试一下就可以调整为自己想要的效果了。src 这里的地址我是使用的模拟数据中的地址,实际使用需要更换一下。 setMapMarker() :geometries 点标记数据数组,此处和高德地图不一致,无需循环生成单个标点,而是通过一个数组直接生成所有的标点。但标点数据的参数需和以下对象一致,具体的的参考注释,没有描述清楚可在评论指出,我会持续更新。 geometries 的数据格式如下: geometries = [{ // 点标记数据
"id": i, //点标记唯一标识,后续如果有删除、修改位置等操作,都需要此id
"styleId": this.iconItem[i].name, // 对应标点实例的style的名称
"position": new TMap.LatLng(this.iconItem[i].position[0], this.iconItem[i].position[1]), // 标点的坐标
"properties": { // 自定义属性,可以根据属性获取参数
"title": this.iconItem[i].name
}]
id:这里我选择使用了循环的 i 值,当然你们可以使用后台返回标点本身的 id。styleId:这里给的是每个标点对应的标点样式名,需要提前规范好样式名称,后台返回数据的时候带上方便处理。position:这里有个比较有意思的事,腾讯地图的坐标参数和高德的坐标参数是相反的,但腾讯地图又通过这个 new TMap.LatLng() 方法把坐标倒转过来👈🤣,大家记得看清楚高德和腾讯的经纬度是相反的。properties:这个自定义属性就看你需要什么,你就直接定义了塞进去就好。
setIcon() { // 创建标点图标
let that = this;
// 创建 AMap.Icon 实例
agriculture = new TMap.MarkerStyle({
"width": 75, // 定义宽,单位:PX
"height": 90, // 定义高,单位:PX
"src": that.iconItem[0].markerUrl, // 标点图片链接:本地图片
})
},
setMapMarker() { // 创建标点实例
let geometries = [];
for (let i = 0; i // 点标记数据
"id": i, //点标记唯一标识,后续如果有删除、修改位置等操作,都需要此id
"styleId": this.iconItem[i].name, // 对应标点实例的style的名称
"position": new TMap.LatLng(this.iconItem[i].position[0], this.iconItem[i].position[1]), // 标点的坐标
"properties": { // 自定义属性,可以根据属性获取参数
"title": this.iconItem[i].name
}
}
geometries.push(obj);
}
marker = new TMap.MultiMarker({ // 构造函数创建标点实例
id: 'marker-layer', // 定义的ID名称
map: mapObj, // 挂载的地图实例
styles: { // 加入标点的样式
"agriculture": agriculture,
"property": property,
"construction": construction,
"noRented": noRented,
},
geometries: geometries // 点标记数据数组
});
},
5、自定义信息框体
实现信息框体功能,实际上就是为标点绑定一个点击事件,点击后再对相应的标点进行渲染。难点主要在如何渲染信息窗体数据并且在信息窗体内绑定点击事件。
效果
![image-20231129154338489](https://img-blog.csdnimg.cn/img_convert/00c3e47595fff6468fbded98734aedf5.png)
代码
let mapObj = null; // 生成组件实例
let area = null; // 生成区域
let agriculture = []; // 生成图标实例
let property = []; // 生成图标实例
let construction = []; // 生成图标实例
let noRented = []; // 生成图标实例
let marker = []; // 生成标点实例
// ------------------------------ 更新内容1 ----------------------------- //
let infoWindow = null; // 自定义信息窗体
let isShowText = false; // 窗体是否打开
// ---------------------------------------------------------------------- //
window.mapInit = function() { // 挂载地图实例
mapObj = new TMap.Map("wrapper", {
center: new TMap.LatLng(22.254515, 113.469689), // 地图初始坐标
zoom: 14, // 缩放等级
mapStyleId: 'style1', // 地图样式
baseMap: { //设置底图样式
type: 'vector', //设置底图为矢量底图
features: [ //设置矢量底图要素类型
'base',
'point'
]
},
zoomControl: false, // 设置是否启用缩放控件
});
// ------------------------------ 更新内容2 ----------------------------- //
infoWindow = new TMap.InfoWindow({ // 设置信息窗体
map: mapObj, // 挂载的地图实例
enableCustom: true, // 是否自定义窗体
position: new TMap.LatLng(22.254515, 113.469689), // 初始标点坐标
offset: { // 信息窗体的偏移量
y: 30,
x: 230
},
content: ``, // 必须设置一个底边的dom,否则会出现白边
});
mapObj.removeControl(TMap.constants.DEFAULT_CONTROL_ID.ZOOM);
mapObj.on("click", function(evt) { // 地图全局事件
//设置infoWindow
if (isShowText) { // 控制是否打开窗体
isShowText = false;
} else {
infoWindow.close();
}
})
// ---------------------------------------------------------------------- //
}
export default {
data() {
return {
key: 'OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77',
// ------------------------------ 更新内容2 ----------------------------- //
iconItem: [{
name: 'agriculture',
src: require("@/static/dot-01.png"),
position: [22.227959, 113.459589],
markerList: [
[
22.22839, 113.460787, 22.227644, 113.460801, 22.227582, 113.45945, 22.228346,
113.459423
]
],
fillColor: 'rgba(35, 181, 29, 0.6)',
fillColorHover: 'rgba(35, 181, 29, 0.8)',
strokeColor: 'rgba(35, 181, 29, 1)',
markerUrl: require("@/static/dot-01.png"),
background: require("@/static/bg-01.png"),
titleUrl: require("@/static/title-01.png"),
}, {
name: 'property',
src: require("@/static/dot-02.png"),
position: [22.253496, 113.477076],
markerList: [
[
22.253749, 113.475984, 22.254632, 113.477205, 22.253963, 113.477805, 22.252339,
113.477209
]
],
fillColor: 'rgba(70, 207, 209, .6)',
fillColorHover: 'rgba(70, 207, 209, .8)',
strokeColor: 'rgba(70, 207, 209, 1)',
markerUrl: require("@/static/dot-02.png"),
background: require("@/static/bg-02.png"),
titleUrl: require("@/static/title-02.png"),
}, {
name: 'construction',
src: require("@/static/dot-03.png"),
position: [22.237834, 113.463987],
markerList: [
[
22.23646, 113.461873, 22.23978, 113.463196, 22.238951, 113.465657, 22.236101,
113.464483
]
],
fillColor: 'rgba(243, 228, 43, .6)',
fillColorHover: 'rgba(243, 228, 43, .8)',
strokeColor: 'rgba(243, 228, 43, 1)',
markerUrl: require("@/static/dot-03.png"),
background: require("@/static/bg-03.png"),
titleUrl: require("@/static/title-03.png"),
}, {
name: 'noRented',
src: require("@/static/dot-04.png"),
position: [22.253692, 113.498333],
markerList: [
[
22.255189, 113.497027, 22.255364, 113.499003, 22.255099, 113.500223, 22.25156,
113.498393, 22.252291, 113.49612, 22.254841, 113.495819
]
],
fillColor: 'rgba(253, 143, 33, .6)',
fillColorHover: 'rgba(253, 143, 33, .8)',
strokeColor: 'rgba(253, 143, 33, 1)',
markerUrl: require("@/static/dot-04.png"),
background: require("@/static/bg-04.png"),
titleUrl: require("@/static/title-04.png"),
}]
// ---------------------------------------------------------------------- //
}
},
onLoad() {
...
},
// ------------------------------ 更新内容3 ----------------------------- //
created() {
let that = this;
window.getParkDetail = function(res) { // 设置信息窗体触发事件
if (res == 0) {
that.isDetail1 = true;
}
if (res == 2) {
that.isDetail2 = true;
}
};
},
// ---------------------------------------------------------------------- //
methods: {
// 初始化
loadScrpit() { // 挂载js
...
},
setIcon() { // 创建标点图标
...
},
// ------------------------------ 更新内容4 ----------------------------- //
setMapMarker() { // 创建标点实例
...
let that = this;
marker.on("click", function(evt) { // 给标点绑定事件打开信息窗体
that.setInfoWindow(evt)
})
},
setInfoWindow(evt) {
let that = this;
// 信息窗体模拟数据,需要使用接口
let imageIcon = require("@/static/icon-22.png");
let background = this.iconItem[0].background;
let titleUrl = this.iconItem[0].titleUrl;
let index = 0;
let titleName = '';
let assetName = '';
let assetNumber = '';
let managementUnit = '';
let assetAddress = '';
let landArea = '';
let backgroundColor = '';
//设置infoWindow
infoWindow.open(); //打开信息窗
infoWindow.setPosition(evt.geometry.position); // 根据当前坐标设置信息窗位置
// console.log(evt.geometry.position);
// 设置点击后的地图偏移的中心点
mapObj.setCenter(new TMap.LatLng((evt.geometry.position.lat + 0.01), (evt.geometry.position
.lng + 0.02)))
if (evt.geometry.properties.title == 'agriculture') { // 根据不同的类型设置标点信息,需要接口代替
background = that.iconItem[0].background;
titleUrl = that.iconItem[0].titleUrl;
index = 0;
titleName = '测试1';
assetName = '农地';
assetNumber = '076地块';
managementUnit = '测试1发展有限公司';
assetAddress = '测试1地块';
landArea = '240072.40m²';
backgroundColor = 'rgba(35, 181, 29, 1)';
}
if (evt.geometry.properties.title == 'property') {
background = that.iconItem[1].background;
titleUrl = that.iconItem[1].titleUrl;
index = 1;
titleName = '测试2';
assetName = '测试2用地';
assetNumber = '037地块';
managementUnit = '测试2有限公司';
assetAddress = '测试2路旁';
landArea = '17979.97m²';
backgroundColor = 'rgba(70, 207, 209, 1)';
}
if (evt.geometry.properties.title == 'construction') {
background = that.iconItem[2].background;
titleUrl = that.iconItem[2].titleUrl;
index = 2;
titleName = '测试3';
assetName = '测试3用地';
assetNumber = '044地块';
managementUnit = '测试3有限公司';
assetAddress = '测试3路旁';
landArea = '14488.01m²';
backgroundColor = 'rgba(243, 228, 43, 1)';
}
if (evt.geometry.properties.title == 'noRented') {
background = that.iconItem[3].background;
titleUrl = that.iconItem[3].titleUrl;
index = 3;
titleName = '测试3';
assetName = '测试3用地';
assetNumber = '099地块';
managementUnit = '测试3有限公司';
assetAddress = '测试3路旁';
landArea = '30667.61m²';
backgroundColor = 'rgba(253, 143, 33, 1)';
}
// 设置信息窗体的样式,通过模板字符串赋值
infoWindow.setContent(`
|