前言
- 很多项目中都会使用到地图,使用的地图基本都是百度、高德、腾讯这些,但是,使用步骤都是大差不差的;
- 就以高德为例,说一下基本的使用流程;
- 下面是使用高德地图的基本流程:
- 注册账号 申请
Key
和 安全密钥
;
- 使用高德地图提供的
jsloader
去加载高德地图的js文件,让它加载到我们的页面中;
- 加载好资源之后,再使用高德地图的API初始化地图;
- 配置地图风格和缩放比例;
- 绘制路线和当前所在位置;
- 本篇文章使用的是
Vue3 + TS
为例写的;
一、准备工作
1.1 注册账号 成为 开发者 获取 Key 和 安全密钥
- 去高德开放平台注册账号、实名认证等;
- 实名认证完成之后,点击控制台;
- 选择 应用管理 ➡ 我的应用 ➡ 创建新应用 ➡ 填写 应用名称 并选择 应用类型;
- 创建好应用之后,点击右边的 添加Key,按照要求填写信息;
- ❗❗ Key名称最好是用英文;

- ❗❗ 注意:
- 服务平台一项 请选择 Web 端 (JSAPI) ;

- 点击提交之后,应用就创建成功了,我们所需要的 Key 和 安全密钥 也就有了;
二、接入高德地图 - JSAPI的加载
2.1 安装高德地图所需的loader
- 🎯 JS API 的加载 🎯;
- 命令:
pnpm add @amap/amap-jsapi-loader --save
;
npm i @amap/amap-jsapi-loader --save
;
2.2 初始化地图
- 初始化 高德地图:
- 高德地图的初始化会操作 DOM ;
- 所以,初始化地图的时机应当是在 组件渲染完毕之后 再进行初始化操作;
Vue3
:
Vue2
:
- 开始使用:
import { onMounted } from 'vue';
import AMapLoader from '@amap/amap-jsapi-loader';
// 开发环境:配置JsCode
// 如果是在 ts 的项目中,这一步会有类型错误,解决方案请移步 2.1.1
window._AMapSecurityConfig = {
securityJsCode:'「您申请的安全密钥」'
};
/** 初始化地图函数 */
onMounted(() => {
// AMapLoader => 加载器
// 资源加载完成后就会触发 then
AMapLoader.load({
"key": "上述步骤得到的key", // 申请好的Web端开发者Key,首次调用 load 时必填
"version": "2.0", // 指定要加载的 JS API 的版本,缺省时默认为 1.4.15
"plugins": [], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then((AMap)=>{
// 初始化地图
const map = new AMap.Map('放置地图的div容器id', {
// 配置对象 - 配置地图的风格和缩放比例,请移步 2.2
});
}).catch(e => {
console.log(e);
});
});
- 效果展示:
- 这就是基本的地图;

2.1.1 解决 window._AMapSecurityConfig 的类型错误
2.2 调节地图的风格 和 缩放比例
const map = new AMap.Map('容器id', {
// 地图风格 - 可以修改地址的最后一个单词来使用不同的风格
mapStyle: 'amap://styles/whitesmoke',
// 缩放比例 - 缩放比例越大,地图就越大,展示的月清晰
zoom: 10
});
- 地图创建之后使用Map对象的setMapStyle方法来修改
map/setMapStyle('amap://styles/whitesmoke')
三、自定义绘制轨迹
- 必须要有 起点 和 终点 的 经纬度坐标;
- 根据地图的自动规划功能,就会得到一条行车路线;
- 地图自动规划的行车路线可能和我们所需要的路线有差别,在项目当中,接口会返回一组由经纬度坐标组成的数组,这时就需要根据经纬度坐标去做细微的绘制;
- 就按照最常使用的物流来说,接口会返回起点、终点坐标,然后就是我们的快递具体到了哪一个中转站,这个中转站会上传当前位置的经纬度坐标,我们根据得到的坐标进行绘制即可;
3.1 使用起点、终点坐标绘制基本路线
- 先根据接口得到的起点和终点坐标,根据地图的自动绘制功能,绘制基本路线;
- 基于上述代码:
// 我们将接口将返回的经纬度数组赋值给 longitudeAndLatitudeList 响应式数据;
// 这里就是模拟一下
const logisticsInfoList = ref([
{latitude: '23.129152403638752', longitude: '113.42775362698366'},
{latitude: '30.454012', longitude: '114.42659'},
{latitude: '31.93182', longitude: '118.633415'},
{latitude: '31.035032', longitude: '121.611504'}
]);
const initMap = () => {
AMapLoader.load({
"key": "上述步骤得到的key", // 申请好的Web端开发者Key,首次调用 load 时必填
"version": "2.0", // 指定要加载的 JS API 的版本,缺省时默认为 1.4.15
"plugins": [], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
})
.then((AMap) => {
// 初始化地图
const map = new AMap.Map('map', {
// 地图风格
mapStyle: 'amap://styles/whitesmoke',
// 缩放比例
zoom: 12
});
// 加载插件 - AMap.Drivin
AMap.plugin('AMap.Driving', function () {
// 插件加载完成后,初始化 Driving 实例
const driving = new AMap.Driving({
// 使用上面得到的地图实例,表示,路径是画在我们当前初始化的这个地图上的
map
});
// 得到 Driving 实例之后,就可以使用 driving.search() 方法,通过起点和终点绘制路径
// 此处最好不要使用 logisticsInfoList 响应式数据进行地图绘制;
// 重新声明一个变量,复制一份经纬度数据
// 有可能我们的经纬度数据是没有的,所以在这块需要进行判断,并且必须 logisticsInfoList.value.length >= 2(必须要有起点 和 终点坐标)
if (logisticsInfoList?.value && logisticsInfoList.value.length >= 2) {
const list = [...logisticsInfoList.value];
// 取出 起点、终点、途径点
const start = list.shift();
const end = list.pop();
// 剩下的list就是途径点
// 该函数接收第四个参数
// 第一个参数:由起点经纬度组成的数组
// 第二个参数:由终点经纬度组成的数组
// 第三个参数:配置对象 - 请移步 3.3
// 第四个参数:函数 - 执行了该函数,就表示路径已经规划完成
driving.search(
[start?.longitude, start?.latitude],
[end?.longitude, end?.latitude],
() => {
// 规划完毕
}
);
};
});
})
.catch(e => {
console.log(e);
});
};
- 注意:
- 在Vue3项目中,不要直接使用接口返回的经纬度坐标数组,
- 该数组通常都是我们使用ref声明的数据进行接收的,如果依然使用该数据的话,页面会受影响的;
- 正确的做法应该是:重新声明一个变量,去复制一份经纬度数组;
- 效果展示:

3.2 关闭实时路况信息
const driving = new AMap.Driving({
map,
// 关闭实时路况信息
showTraffic: false
});
- 效果展示:

3.3 根据途径点自定义绘制路径
driving.search(
[start?.longitude, start?.latitude],
[end?.longitude, end?.latitude],
// waypoints:该属性的属性值为由经纬度数组组成的数组,也就是说该属性的属性值是个二维数组
{ waypoints: list.map((item) => [item.longitude, item.latitude]) },
() => {
// 执行了这个函数,就表示路径已经规划完毕
}
);
- 效果展示:

3.4 关闭沿途标记点
const driving = new AMap.Driving({
// 使用上面得到的地图实例,表示,路径是画在我们当前初始化的这个地图上的
map,
// 关闭实时路况信息
showTraffic: false,
// 关闭途径点icon
hideMarkers: true
});
- 效果展示:

- 问题:
- 关闭途径点之后,起点和终点的标志也就不显示了;
- 请看下节;
四、绘制 标记 以及 当前位置
4.1 绘制标记
4.1.1 ❌ 直接使用图片的URL
- ❗❗ 缺陷:
- 按照这种方式设置的标记点是 无法调整
icon
的大小;
- 图片多大,标记显示的就是多大;
import startImg from '@/assets/images/start.png';
// 取出 起点、终点、途径点
const start = list.shift();
// 创建起点
const marker = new AMap.Marker({
// 经纬度坐标
position: [start?.longitude, start?.latitude],
// 需要展示的图标
icon: startImg
});
// 将创建的标记点加到地图上(此处的map就是上述创建的地图实例)
map.add(marker);

- 缺陷:
- 标记点虽然绘制上了,但是标记点和大小和位置不对,但是这种方式不支持设置图片的样式;
4.1.2 ✅ 创建 AMap.Icon 实例 绘制标记
- 优点:
- 可以设置图标的大小
size
,偏移imageOffset
等属性,比单纯设置URL更具灵活性;
import startImg from '@/assets/images/start.png';
// 取出 起点、终点、途径点
const start = list.shift();
// 创建起点
const icon = new AMap.Icon({
// 图标尺寸 ===> new AMap.Size(宽, 高)
size: new AMap.Size(25, 30),
// Icon图片
image: startImg,
// 根据所设置的大小拉伸或压缩图片 ===> new AMap.Size(宽, 高)
imageSize: new AMap.Size(25, 30)
});
const marker = new AMap.Marker({
// 经纬度坐标
position: [start?.longitude, start?.latitude],
// 需要展示的图标
icon
});
// 将创建的标记点加到地图上(此处的map就是上述创建的地图实例)
map.add(marker);
- 效果展示:

4.1.3 设置图标的偏移
- 不管是使用哪种方式设置的标记,都可以发现,图像的左上角和我们的起点位置是重合的;
- 设置偏移量的话,就将图片向左偏移宽度的一半,向上偏移高度的100%即可;
const marker = new AMap.Marker({
// 经纬度坐标
position: [start?.longitude, start?.latitude],
// 需要展示的图标
icon,
// 设置偏移量 ===> new AMap.Pixel(X轴方向的偏移量, Y轴方向的偏移量)
offset: new AMap.Pixel(-12.5, -30)
});
- 效果展示:

4.2 封装绘制标记函数
- 由于我们代码的标记不止一处,我们可以将绘制标记的代码封装成一个函数,使用的时候,直接传递经纬度,图片的地址,大小,偏移量等等;
- 类型文件:
// 文件路径:src/types/order.d.ts
export type Location = {
/** 经度 */
longitude: string;
/** 纬度 */
latitude: string;
};
- 封装绘制标记函数:
- 注意点:
- 要将该函数封装在
AMapLoader.load
的 then
回调中;
import type { Location } from '@/types/order';
import startImg from '@/assets/start.png';
/**
* 创建标记函数
* @param point 经纬度坐标
* @param image 图片
* @param width 图片宽度
* @param height 图片高度
*/
const createMarker = (
point: Location,
image: string,
width: number = 25,
height: number = 30
) => {
// 创建icon实例
const icon = new AMap.Icon({
// 图标尺寸 ===> new AMap.Size(宽, 高)
size: new AMap.Size(width, height),
// Icon图片
image,
// 根据所设置的大小拉伸或压缩图片 ===> new AMap.Size(宽, 高)
imageSize: new AMap.Size(width, height)
});
// 创建标记
const marker = new AMap.Marker({
// 经纬度坐标
position: [point?.longitude, point?.latitude],
// 需要展示的图标
icon,
// 图像相对展示区域的偏移量 ===> new AMap.Pixel(X轴方向的偏移量, Y轴方向的偏移量)
offset: new AMap.Pixel(-width / 2, -height)
});
return marker;
};
- 使用函数:
// 取出 起点、终点、途径点
const start = list.shift();
// 将创建的标记点加到地图上
// 这块会提示start可能不存在,使用 ! 进行非空断言
map.add(createMarker(start!, startImg, 25, 30));

- 效果展示:

4.3 标记当前所在位置
// 当前位置坐标
// 我这里就是模拟,实际的项目中,也是通过接口返回的
// 绘制当前位置的时机,最好是在路径已经规划完毕之后再去绘制
import carImg from '@/assets/car.png';
const currentLocationInfo = ref({"latitude":"31.93182","longitude":"118.633415"});
driving.search(
[start?.longitude, start?.latitude],
[end?.longitude, end?.latitude],
{ waypoints: list.map((item) => [item.longitude, item.latitude]) },
() => {
// 执行了这个函数,就表示路径已经规划完毕
// 绘制当前位置,最好是在路径规划完成之后绘制
// 获取当前点位
const curr = currentLocationInfo.value;
map.add(createMarker(curr!, carImg, 25, 20));
}
);
- 效果展示:

4.4 调整当前位置到地图正中央及调整缩放比例
driving.search(
[start?.longitude, start?.latitude],
[end?.longitude, end?.latitude],
{ waypoints: list.map((item) => [item.longitude, item.latitude]) },
() => {
// 执行了这个函数,就表示路径已经规划完毕
// 绘制当前位置,最好是在路径规划完成之后绘制
// 获取当前点位
const curr = logistics.value?.currentLocationInfo;
const currMarker = createMarker(curr!, carImg, 25, 20);
map.add(currMarker);
// 先展示整个路径,三秒后定位到地图的正中央
setTimeout(() => {
// 定位到地图正中央
// 第一个参数,是有 marker 组成的数组
map.setFitView([currMarker]);
// 设置缩放比例
map.setZoom(10);
}, 3000);
}
);
- 效果展示:
