一、前言
因为公司的业务需求,需要实现一个接入高德地图的数据大屏,并根据坐标实现地图标点渲染,自定义信息窗体,点击定位等功能。查阅高德地图官方文档时发现使用的是原生 JavaScript ,且网上 uniapp 接入使用的教程较少,我自己摸索之后解决了不少问题,欢迎大佬补充纠正。
📌 更新了一篇 腾讯地图 的博客,并附有demo,大家可以根据需求来选用:地址
二、准备工作
1、参考博客以及相关地址
高德开发平台:平台地址
注册参考博客:博客地址
2、注册高德开发平台账号
我们需要先在高德开放平台注册一个账号,以申请获取 key 等权限信息。注册流程很简单,就不赘述了,获取成功后点击此处:
![image-20230504100153524](https://img-blog.csdnimg.cn/img_convert/4f9cdfbb9196f6656b53f3b0a52c26dc.png)
点击创建新应用,至于里面的内容就是随便填都可以:
![image-20230504100638922](https://img-blog.csdnimg.cn/img_convert/5f4eb70ade5af30bdc2dd7efe9498223.png)
点击添加 Key ,创建你的 Key 值,我们后面都需要使用,具体你是哪个开发平台就勾选哪一个:
![image-20230504100932468](https://img-blog.csdnimg.cn/img_convert/4f4a05f1f37f972cd5fae81b6a1f446e.png)
下面是最后生成的 Key。在参考博客中是直接使用 key 获取并本地导入下载的SDK,而我使用的是动态导入,大家可以尝试一下哪个更适合你的开发。
![image-20230504101121345](https://img-blog.csdnimg.cn/img_convert/534baf6c117cde632a28dc9d319d8aa2.png)
三、导入以及使用
以下内容较多篇幅较长,大家可以根据目录选择阅读,我会结合官方文档以及参考文档详细说明每一个方法的使用以及具体实现,但最好还是按顺序看下去。
1、参考博客与文档以及相关地址
高德官方文档:地址
开发参考博客:地址(不是我的博客)
实际上该博客相当于官方文档的导读摘要,大家可以看看哪些是你需要的,去官方文档再详细看就好了
2、导入SDK
在导入这一块我尝试了很多种方法,最终实现的是这个方法:怎么引入高德地图 ,通过这个方法可以定义一个全局的地图实例供我们调用高德API。
效果
![image-20230504142312187](https://img-blog.csdnimg.cn/img_convert/0ca1369b9e45c456339b3d5913fce021.png)
代码
let mapObj = null; // 生成地图实例
window.mapInit = function() {
mapObj = new AMap.Map('wrapper', {
center: [113.382, 22.5211],
layers: [
new AMap.TileLayer.Satellite(), // 卫星
new AMap.TileLayer.RoadNet() // 路网
],
zoom: 13
});
// 在这里可以做一些回调处理 定位 标记点 等等 或者把amap弄成一个全局变量
// 引入单个插件
AMap.plugin('AMap.ToolBar', function() { // 异步加载插件
var toolbar = new AMap.ToolBar();
map.addControl(toolbar);
});
};
export default {
data() {},
onLoad() {
// #ifdef H5
this.loadScrpit();
// #endif
},
methods: {
loadScrpit() { // 挂载动态js
var script = document.createElement('script');
script.src = 'https://webapi.amap.com/maps?v=1.4.15&key=(这里是你申请的KEY)&callback=mapInit';
document.body.appendChild(script);
},
}
}
代码讲解
首先是在 onLoad() 在页面加载阶段内调用动态挂载函数,熟悉原生 JavaScript 的朋友都应该可以明白这是一个创建 标签,并把它插入 body 内的操作。关键是在标签的属性上,我们需要传入 Key 值和回调函数。
📌 此处的回调函数可以取任意名,但需要注意的是在 window.function() 接收函数时需要同名,否则无法成功接收回调函数。
mapObj = new AMap.Map('wrapper', {
center: [Longitude, Latitude],
layers: [
new AMap.TileLayer.Satellite(), // 卫星
new AMap.TileLayer.RoadNet() // 路网
],
zoom: 13
});
在本文中我使用 mapObj 全局存储地图的实例, new AMap.Map('id',Object) 的参数:
id:地图将会渲染在同名 id 的 view 或 div 内。 📍 需要注意的是,如果你想要在地图上自定义一些控件或展示框,最好不在该标签内添加,因为当你定位到一个新的地点时,它将刷新整个地图,你所定义的界面将会全部消失。正确的做法应该是建立一个同级的标签,通过 z-index 属性置于地图的上层。
Object:你可以通过该对象决定你的地图需要哪些图层与初始定位,还有缩放的级数。
center:[ Longitude , Latitude ] ,设置中心点的位置;layers:根据业务需求决定需要什么图层,常用应该只有卫星和路网这两种;zoom:初始地图的缩放级数,同样也是根据你的业务需求设置就好了。
3、点击坐标定位
点击代码实际上和挂载地图是一样的代码,只需要修改中心点的位置,重新挂载即可。但问题也随之出现,如果你已经设置了标点坐标与信息窗体,重新挂载后将会消除这些信息,你需要再次挂载这些信息。也就是说你如果需要保存定位前的标点,需要先保存对应的坐标。
代码
mapObj = new AMap.Map('wrapper', {
center: [Longitude, Latitude],
layers: [
new AMap.TileLayer.Satellite(), // 卫星
new AMap.TileLayer.RoadNet() // 路网
],
zoom: 13
});
代码讲解
基本和上面说的一样,只要替换中心的定位坐标即可。在下面你会了解到如何挂载自定义标点与信息窗体,这些信息都会在你定位后消失,需要重新挂载,也就是保存坐标信息再次挂载坐标标点。
4、自定义标点
自定义标点主要是定义图标的图像以及大小、偏移量等参数。需要注意的是,标点自定义必须在地图实例挂载之后,否则无法定义成功。自定义标点信息成功后再挂载标点,最后实现的就是下图效果。
效果
![image-20230612101134611](https://img-blog.csdnimg.cn/img_convert/55787861ce24dbdf13568ccc073bf88d.png)
代码
let mapObj = null; // 生成地图实例
// ------------------------------ 更新内容1 ----------------------------- //
let icon = null; // 生成图片实例
let punctuation = []; // 生成标点实例
// ---------------------------------------------------------------------- //
window.mapInit = function() {
mapObj = new AMap.Map('wrapper', {
center: [Longitude, Latitude],
layers: [
new AMap.TileLayer.Satellite(), // 卫星
new AMap.TileLayer.RoadNet() // 路网
],
zoom: 13
});
// 在这里可以做一些回调处理 定位 标记点 等等 或者把amap弄成一个全局变量
// 引入单个插件
AMap.plugin('AMap.ToolBar', function() { // 异步加载插件
var toolbar = new AMap.ToolBar();
map.addControl(toolbar);
});
};
export default {
data() {},
onLoad() {
// #ifdef H5
this.loadScrpit();
// #endif
// ------------------------------ 更新内容2 ----------------------------- //
let time = setInterval(() => { // 等待地图挂载后再自定义标点
if (mapObj != null) {
this.setIcon(); // 挂载坐标图片信息
this.getCoordinateList(type); // 获取坐标
clearInterval(time);
}
}, 100)
// ---------------------------------------------------------------------- //
},
methods: {
loadScrpit() { // 挂载动态js
var script = document.createElement('script');
script.src = 'https://webapi.amap.com/maps?v=1.4.15&key=(这里是你申请的KEY)&callback=mapInit';
document.body.appendChild(script);
},
// ------------------------------ 更新内容3 ----------------------------- //
setIcon() { // 设置icon
// 创建 AMap.Icon 实例
icon = new AMap.Icon({
size: new AMap.Size(48, 60), // 图标尺寸
image: "image.png", // Icon的图像
imageSize: new AMap.Size(48, 60), // 根据所设置的大小拉伸或压缩图片
imageOffset: new AMap.Pixel(0, 0) // 图像相对展示区域的偏移量,适于雪碧图等
});
},
getCoordinateList(type) { // 获取坐标
uni.request({
url: this.url_str, // 你的请求后台的地址
method: 'GET',
data: {
region: '你的地区参数',
},
success: (e) => {
console.log(e);
mapObj.remove(punctuation);
this.setMapMarkerList(this.list); // 赋予坐标图片标点
}
})
},
setMapMarkerList(list) { // 批量生成标点
let that = this;
// console.log(list);
list.forEach(function(marker) {
let punctuationItem = new AMap.Marker({
map: mapObj,
icon: icon,
position: [marker.Longitude, marker.Latitude],
offset: new AMap.Pixel(-13, -30)
});
punctuation.push(punctuationItem);
});
},
// ---------------------------------------------------------------------- //
}
}
代码讲解
更新内容1:创建全局的图片的实例 icon,只需要创建一次,直到更换标点图案。全局的标点按需加载,每次跳转与切换坐标定位,都需要重新挂载。
let icon = null; // 生成标点图片实例
let punctuation = []; // 生成标点实例
更新内容2:在 onLoad() 里设置定时器监听地图是否挂载成功,没挂载地图实例前无法挂载标点图片与坐标标点。一旦监听到地图组件挂载便取消对应的定时器监听。
let time = setInterval(() => { // 等待地图挂载后再自定义标点
if (mapObj != null) {
this.setIcon(); // 挂载坐标图片信息
this.getCoordinateList(type); // 获取坐标并挂载坐标标点
clearInterval(time);
}
}, 100)
更新内容3:
setIcon(): 设置自定义标点图片的参数,具体的参数看下面介绍,按照对应的测试一下就可以调整为自己想要的效果了。getCoordinateList(): 请求获取所需的坐标信息,在赋予标点时需要根据对应的坐标信息进行挂载。这里需要注意的是 mapObj.remove(punctuation) 这行代码,它用于去除过往的标点,当你需要根据不同的地区筛选时就需要使用这个去除旧的标点。setMapMarkerList():请求标点后,调用该函数传入标点坐标,通过循环批量生成标点,并且存入 punctuation 以备后期需要消除标点使用。
setIcon() { // 设置icon
// 创建 AMap.Icon 实例
icon = new AMap.Icon({
size: new AMap.Size(48, 60), // 图标尺寸
image: "image.png", // Icon的图像
imageSize: new AMap.Size(48, 60), // 根据所设置的大小拉伸或压缩图片
imageOffset: new AMap.Pixel(0, 0) // 图像相对展示区域的偏移量,适于雪碧图等
});
},
getCoordinateList(type) { // 获取坐标
uni.request({
url: this.url_str, // 你的请求后台的地址
method: 'GET',
data: {
region: '你的地区参数',
},
success: (e) => {
console.log(e);
mapObj.remove(punctuation);
this.list = e.data.list;
this.setMapMarkerList(this.list); // 赋予坐标图片标点
}
})
},
setMapMarkerList(list) { // 批量生成标点
let that = this;
// console.log(list);
list.forEach(function(marker) {
let punctuationItem = new AMap.Marker({
map: mapObj,
icon: icon,
position: [marker.Longitude, marker.Latitude],
offset: new AMap.Pixel(-13, -30)
});
punctuation.push(punctuationItem);
});
},
5、自定义信息框体
实现信息框体功能,实际上就是为标点绑定一个点击事件,点击后再对相应的标点进行渲染。难点主要在如何渲染信息窗体数据并且在信息窗体内绑定点击事件。
效果
![image-20230616154841089](https://img-blog.csdnimg.cn/img_convert/1c2643ba76b33bea9180988b373b11df.png)
代码
let mapObj = null; // 生成地图实例
let icon = null; // 生成图片实例
let punctuation = []; // 生成标点实例
// ------------------------------ 更新内容1 ----------------------------- //
let infoWindow = null // 信息窗体
let isShowText = false; // 窗体是否打开
// ---------------------------------------------------------------------- //
window.mapInit = function() {
mapObj = new AMap.Map('wrapper', {
center: [Longitude, Latitude],
layers: [
new AMap.TileLayer.Satellite(), // 卫星
new AMap.TileLayer.RoadNet() // 路网
],
zoom: 13
});
// ------------------------------ 更新内容2 ----------------------------- //
mapObj.on('click', () => {
if (isShowText) {
isShowText = false;
infoWindow.close();
}
});
infoWindow = new AMap.InfoWindow({
offset: new AMap.Pixel(0, -30),
isCustom: true,
});
// ---------------------------------------------------------------------- //
// 在这里可以做一些回调处理 定位 标记点 等等 或者把amap弄成一个全局变量
// 引入单个插件
AMap.plugin('AMap.ToolBar', function() { // 异步加载插件
var toolbar = new AMap.ToolBar();
map.addControl(toolbar);
});
};
export default {
data() {},
onLoad() {
// #ifdef H5
this.loadScrpit();
// #endif
let time = setInterval(() => { // 等待地图挂载后再自定义标点
if (mapObj != null) {
this.setIcon(); // 挂载坐标图片信息
this.getCoordinateList(type); // 获取坐标
clearInterval(time);
}
}, 100)
},
// ------------------------------ 更新内容3 ----------------------------- //
created() {
let that = this;
window.getParkDetail = function() {
that.isBottomShow = false;
that.isList = false;
isShowText = false;
infoWindow.close();
};
},
// ---------------------------------------------------------------------- //
methods: {
loadScrpit() { // 挂载动态js
var script = document.createElement('script');
script.src = 'https://webapi.amap.com/maps?v=1.4.15&key=(这里是你申请的KEY)&callback=mapInit';
document.body.appendChild(script);
},
setIcon() { // 设置icon
...
},
getCoordinateList(type) { // 获取坐标
...
},
setMapMarkerList(list) { // 批量生成标点
let that = this;
// console.log(list);
list.forEach(function(marker) {
let punctuationItem = new AMap.Marker({
map: mapObj,
icon: icon,
position: [marker.Longitude, marker.Latitude],
offset: new AMap.Pixel(-13, -30)
});
// ----------------------------- 更新内容4 ----------------------------- //
punctuationItem.Id = marker.Id;
punctuationItem.on('click', that.markerClick);
// -------------------------------------------------------------------- //
punctuation.push(punctuationItem);
});
},
// ------------------------------ 更新内容5 ----------------------------- //
markerClick(e) {
let that = this;
uni.request({
url: this.url_str,
method: 'GET',
data: {
Id: e.target.Id,
},
success: (res) => {
let content =
`
|