Vue3+vite对接高德地图实现公交路线规划
说明
这里记录下自己在Vue3+vite的项目中增加对接高德地图通过输入起始站和终点站来实现公交路线规划,不使用ts语法,方便以后直接使用。这里承接自己的博客Vue3+vite优化基础架构(2)— 全局接口请求loading加载这篇博客,在该博客项目的基础上增加对接高德地图通过输入起始站和终点站来实现公交路线规划。
高德开放平台:https://lbs.amap.com/
高德开放平台JS Api文档:https://lbs.amap.com/api/javascript-api-v2/guide/services/navigation
高德开放平台-公交路线规划官网Demo:https://lbs.amap.com/demo/javascript-api-v2/example/bus-search/plan-route-according-to-name
第一步:在高德开放平台注册账号
如果没有高德开放平台的账号,可以在高德开放平台右上角点击注册,注册一个账号。如下:
第二步:选择认证方式
这里因为我是尝试做一个Demo,所以选择个人支付宝扫码认证。
第三步:完善信息
这里我填写的自己的QQ邮箱。
第四步:在高德开发平台中应用管理-我的应用-创建新应用
这里应用名称我叫MyMap,应用类型选为导航类型。
添加Key:
这里因为我是用前端对接,所以选用Web端(JS API):
新建完成后应用管理-我的应用会多出一条数据,如下:
第五步:Vue3项目代码开发
在Vue3项目中安装高德地图依赖:
npm install @amap/amap-jsapi-loader --save
package,json如下:
在components文件夹下创建map-container组件:
map-container组件代码如下:
<template>
<div id="container"></div>
</template>
<script setup>
import {onMounted, onUnmounted, ref} from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
//地图
const map = ref(null);
onMounted(() => {
window._AMapSecurityConfig = {
securityJsCode: "我的应用中的安全密钥", // 申请好的Web端开发者安全密钥
};
// 异步加载多个插件
AMapLoader.load({
key: "我的应用中的Key", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [], //需要使用的的插件列表,支持添加多个如:['...','...']
}).then((AMap) => {
// 创建地图
map.value = new AMap.Map("container", {
// 设置地图容器id
viewMode: "3D", // 是否为3D地图模式
mapStyle: "amap://styles/normal", //设置地图的显示样式
zoom: 10, // 初始化地图级别
// center: [116.397428, 39.90923], // 初始化地图中心点位置,这个是北京的经纬度,不填默认定位你在的城市,如果有定位功能,需要注释掉该行属性
});
})
.catch((e) => {
console.log(e);
});
});
onUnmounted(() => {
map.value?.destroy();
});
</script>
<style lang="less" scoped>
#container {
width: 100%;
height: 84vh;
}
</style>
然后在test-management2页面中引入该组件。
页面效果展示:默认定位我所在的城市广州市。
添加工具条控件、比例尺控件、鹰眼控件、类别切换控件、控制罗盘控件。有需要可以添加,不需要无须添加。代码如下:
<template>
<div id="container"></div>
</template>
<script setup>
import {onMounted, onUnmounted, ref} from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
//地图
const map = ref(null);
onMounted(() => {
window._AMapSecurityConfig = {
securityJsCode: "我的应用中的安全密钥", // 申请好的Web端开发者安全密钥
};
// 异步加载多个插件
AMapLoader.load({
key: "我的应用中的Key", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ["AMap.Scale","AMap.ToolBar","AMap.HawkEye","AMap.MapType","AMap.ControlBar"], // 需要使用的的插件列表,支持添加多个如:['...','...']
}).then((AMap) => {
// 创建地图
map.value = new AMap.Map("container", {
// 设置地图容器id
viewMode: "3D", // 是否为3D地图模式
mapStyle: "amap://styles/normal", //设置地图的显示样式
zoom: 10, // 初始化地图级别
// center: [116.397428, 39.90923], // 初始化地图中心点位置,这个是北京的经纬度,不填默认定位你在的城市,如果有定位功能,需要注释掉该行属性
});
// 添加比例尺控件,展示地图在当前层级和纬度下的比例尺
map.value.addControl(new AMap.Scale());
// 添加工具条控件,工具条控件集成了缩放、平移、定位等功能按钮在内的组合控件
map.value.addControl(new AMap.ToolBar());
// 添加鹰眼控件,在地图右下角显示地图的缩略图
map.value.addControl(new AMap.HawkEye({ isOpen: true }));
// 添加类别切换控件,实现默认图层与卫星图、实施交通图层之间切换的控制
map.value.addControl(new AMap.MapType());
// 添加控制罗盘控件,用来控制地图的旋转和倾斜
map.value.addControl(new AMap.ControlBar());
})
.catch((e) => {
console.log(e);
});
});
onUnmounted(() => {
map.value?.destroy();
});
</script>
<style lang="less" scoped>
#container {
width: 100%;
height: 84vh;
}
</style>
页面效果展示:
这里之所以看不到工具条控件是因为鹰眼控件给挡住了,2个控件默认都是在右下角显示。
接下来的代码才是核心,根据输入的地点关键字下拉获取对应站点,代码如下:
<template>
<div>
<el-form
ref="formRef"
:rules="formRules"
:model="form"
label-width="100px"
>
<el-row>
<el-col :span="8">
<el-form-item label="起始站:" prop="departureStation">
<!-- filterable:Select组件是否可筛选,默认为false -->
<!-- remote:其中的选项是否从服务器远程加载,默认为false -->
<!-- remote-method:自定义远程搜索方法 -->
<!-- loading:是否正在从远程获取数据,默认为false -->
<el-select
v-model="form.departureStation"
filterable
remote
placeholder="请输入起始站"
:remote-method="remoteMethod"
:loading="loading"
>
<el-option
v-for="item in options"
:key="item.id"
:label="item.name"
:value="item.name"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="终点站:" prop="arrivalStation">
<el-select
v-model="form.arrivalStation"
filterable
remote
placeholder="请输入终点站"
:remote-method="remoteMethod"
:loading="loading"
>
<el-option
v-for="item in options"
:key="item.id"
:label="item.name"
:value="item.name"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" style="padding-left: 20px;">
<el-button type="primary">查 询</el-button>
<el-button>清 空</el-button>
</el-col>
</el-row>
</el-form>
</div>
<div id="container"></div>
</template>
<script setup>
import {onMounted, onUnmounted, ref, reactive} from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
// 表单ref名称
const formRef = ref()
// 表单mode名称和表单字段
const form=reactive({
departureStation: '',// 始发站
arrivalStation: ''// 到达站
})
// 表单校检规则
const formRules = reactive({
// 始发站校检规则
departureStation: [
{
required: true,
message: '始发站不能为空!',
trigger: 'blur'
}
],
// 机型校检规则
arrivalStation: [
{
required: true,
message: '到达站不能为空!',
trigger: 'blur'
}
]
})
// 下拉框选择值
const options = ref([])
// 是否正在从远程获取数据,默认为false
const loading = ref(false)
// 搜索回调方法
const remoteMethod = (val) => {
if (val) {
loading.value = true
setTimeout(() => {
loading.value = false
// 获取输入提示信息
autoInput(val)
}, 200)
} else {
options.value = []
}
}
// 获取输入提示信息
const autoInput = (val) => {
// 引用AMap.AutoComplete插件
AMap.plugin("AMap.AutoComplete", function () {
// 注意:输入提示插件2.0版本需引入AMap.AutoComplete,而1.4版本应使用AMap.Autocomplete
// 实例化AutoComplete
var autoOptions = {
city: "全国",
};
var autoComplete = new AMap.AutoComplete(autoOptions);
autoComplete.search(val, function (status, result) {
if (status === "complete" && result.info === "OK") {
// 搜索成功时,result即是对应的匹配数据
// console.info(result)
options.value =result.tips
}
});
});
}
//地图
const map = ref(null);
onMounted(() => {
window._AMapSecurityConfig = {
securityJsCode: "我的应用中的安全密钥", // 申请好的Web端开发者安全密钥
};
// 异步加载多个插件
AMapLoader.load({
key: "我的应用中的Key", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ["AMap.Scale","AMap.ToolBar","AMap.HawkEye","AMap.MapType","AMap.ControlBar"], // 需要使用的的插件列表,支持添加多个如:['...','...']
}).then((AMap) => {
// 创建地图
map.value = new AMap.Map("container", {
// 设置地图容器id
viewMode: "3D", // 是否为3D地图模式
mapStyle: "amap://styles/normal", // 设置地图的显示样式
zoom: 10, // 初始化地图级别
// center: [116.397428, 39.90923], // 初始化地图中心点位置,这个是北京的经纬度,不填默认定位你在的城市,如果有定位功能,需要注释掉该行属性
});
//添加比例尺控件,展示地图在当前层级和纬度下的比例尺
map.value.addControl(new AMap.Scale());
//添加工具条控件,工具条控件集成了缩放、平移、定位等功能按钮在内的组合控件
map.value.addControl(new AMap.ToolBar());
//添加鹰眼控件,在地图右下角显示地图的缩略图
map.value.addControl(new AMap.HawkEye({ isOpen: true }));
//添加类别切换控件,实现默认图层与卫星图、实施交通图层之间切换的控制
map.value.addControl(new AMap.MapType());
//添加控制罗盘控件,用来控制地图的旋转和倾斜
map.value.addControl(new AMap.ControlBar());
})
.catch((e) => {
console.log(e);
});
});
onUnmounted(() => {
map.value?.destroy();
});
</script>
<style lang="less" scoped>
#container {
width: 100%;
height: 84vh;
}
</style>
页面效果展示:在这里插入图片描述
现在已经可以实现文本框搜索地铁站了,接下来就是点击查询按钮进行路线显示了。代码如下:
<template>
<div>
<el-form
ref="formRef"
:rules="formRules"
:model="form"
label-width="100px"
>
<el-row>
<el-col :span="8">
<el-form-item label="起始站:" prop="departureStation">
<!-- filterable:Select组件是否可筛选,默认为false -->
<!-- remote:其中的选项是否从服务器远程加载,默认为false -->
<!-- remote-method:自定义远程搜索方法 -->
<!-- loading:是否正在从远程获取数据,默认为false -->
<el-select
v-model="form.departureStation"
filterable
remote
placeholder="请输入起始站"
:remote-method="remoteMethod"
:loading="loading"
>
<el-option
v-for="item in options"
:key="item.id"
:label="item.name"
:value="item.name"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="终点站:" prop="arrivalStation">
<el-select
v-model="form.arrivalStation"
filterable
remote
placeholder="请输入终点站"
:remote-method="remoteMethod"
:loading="loading"
>
<el-option
v-for="item in options"
:key="item.id"
:label="item.name"
:value="item.name"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" style="padding-left: 20px;">
<el-button type="primary" @click="onQuery(formRef)">查 询</el-button>
<el-button @click="onReset(formRef)">清 空</el-button>
</el-col>
</el-row>
</el-form>
</div>
<div id="container"></div>
<div id="panel"></div>
</template>
<script setup>
import {onMounted, onUnmounted, ref, reactive} from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
// 表单ref名称
const formRef = ref()
// 表单mode名称和表单字段
const form=reactive({
departureStation: '',// 始发站
arrivalStation: ''// 到达站
})
// 表单校检规则
const formRules = reactive({
// 始发站校检规则
departureStation: [
{
required: true,
message: '始发站不能为空!',
trigger: 'blur'
}
],
// 机型校检规则
arrivalStation: [
{
required: true,
message: '到达站不能为空!',
trigger: 'blur'
}
]
})
// 下拉框选择值
const options = ref([])
// 是否正在从远程获取数据,默认为false
const loading = ref(false)
// 搜索回调方法
const remoteMethod = (val) => {
if (val) {
loading.value = true
setTimeout(() => {
loading.value = false
// 获取输入提示信息
autoInput(val)
}, 200)
} else {
options.value = []
}
}
// 获取输入提示信息
const autoInput = (val) => {
// 引用AMap.AutoComplete插件
AMap.plugin("AMap.AutoComplete", function () {
// 注意:输入提示插件2.0版本需引入AMap.AutoComplete,而1.4版本应使用AMap.Autocomplete
// 实例化AutoComplete
var autoOptions = {
city: "全国",
};
var autoComplete = new AMap.AutoComplete(autoOptions);
autoComplete.search(val, function (status, result) {
if (status === "complete" && result.info === "OK") {
// 搜索成功时,result即是对应的匹配数据
// console.info(result)
options.value =result.tips
}
});
});
}
// 所在城市
const cityInfo = ref('')
// 获取用户所在城市信息
const showCityInfo = () => {
AMap.plugin("AMap.CitySearch", function () {
// 实例化城市查询类
let citysearch = new AMap.CitySearch();
// 自动获取用户IP,返回当前城市
citysearch.getLocalCity(function(status, result) {
if (status === 'complete' && result.info === 'OK') {
if (result && result.city && result.bounds) {
cityInfo.value = result.city; // 当前所在城市
let citybounds = result.bounds; // 当前所在经纬度
//地图显示当前城市
map.value.setBounds(citybounds);
console.info('您当前所在城市:'+cityInfo.value)
console.info('您当前所在经纬度:'+citybounds)
}
} else {
//document.getElementById('info').innerHTML = result.info || '暂无数据';
}
})
})
}
// 表单查询按钮事件
const queryStation = () => {
var transOptions = {
map: map.value,
panel: 'panel',
policy: AMap.TransferPolicy.LEAST_TIME //乘车策略
};
// 构造公交换乘类
var transfer = new AMap.Transfer(transOptions);
// 根据起、终点名称查询公交换乘路线
transfer.search([
{ keyword: form.departureStation, city: cityInfo.value },// 起始站
// 第一个元素city缺省时取transOptions的city属性
{ keyword: form.arrivalStation, city: cityInfo.value } // 到达站
// 第二个元素city缺省时取transOptions的cityd属性
], function (status, result) {
// result即是对应的公交路线数据信息,相关数据结构文档请参考 https://lbs.amap.com/api/javascript-api/reference/route-search#m_TransferResult
if (status === 'complete') {
console.info('绘制公交路线完成')
//console.info('result=',result)
} else {
console.error('公交路线数据查询失败' + result)
}
});
}
// 表单查询按钮事件
const onQuery = (formRef) => {
if (!formRef) return
// 对表单进行一个校验
formRef.validate((valid) => {
if (valid) {
// 每次查询前移除之前查询的公交路线,不然会在已有的路线上继续追加当前查询的路线结果
document.getElementById('panel').innerHTML=""
// 校检成功调用查询接口
queryStation()
} else {
//console.log('校验失败error!')
return false
}
})
}
// 表单清空按钮事件
const onReset = (formRef) => {
if (!formRef) return
formRef.resetFields()
}
// 地图
const map = ref(null);
onMounted(() => {
window._AMapSecurityConfig = {
securityJsCode: "我的应用中的安全密钥", // 申请好的Web端开发者安全密钥
};
// 异步加载多个插件
AMapLoader.load({
key: "我的应用中的Key", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ["AMap.Scale","AMap.ToolBar","AMap.HawkEye","AMap.MapType","AMap.ControlBar","AMap.Transfer","AMap.Adaptor"], // 需要使用的的插件列表,支持添加多个如:['...','...']
}).then((AMap) => {
// 创建地图
map.value = new AMap.Map("container", {
// 设置地图容器id
viewMode: "3D", // 是否为3D地图模式
mapStyle: "amap://styles/normal", // 设置地图的显示样式
zoom: 10, // 初始化地图级别
// center: [116.397428, 39.90923], // 初始化地图中心点位置,这个是北京的经纬度,不填默认定位你在的城市,如果有定位功能,需要注释掉该行属性
});
// 添加比例尺控件,展示地图在当前层级和纬度下的比例尺
map.value.addControl(new AMap.Scale());
// 添加工具条控件,工具条控件集成了缩放、平移、定位等功能按钮在内的组合控件
map.value.addControl(new AMap.ToolBar());
// 添加鹰眼控件,在地图右下角显示地图的缩略图
map.value.addControl(new AMap.HawkEye({ isOpen: true }));
// 添加类别切换控件,实现默认图层与卫星图、实施交通图层之间切换的控制
map.value.addControl(new AMap.MapType());
// 添加控制罗盘控件,用来控制地图的旋转和倾斜
map.value.addControl(new AMap.ControlBar());
// 获取城市信息
showCityInfo();
})
.catch((e) => {
console.log(e);
});
});
onUnmounted(() => {
map.value?.destroy();
});
</script>
<style lang="less" scoped>
#container {
width: 100%;
height: 84vh;
}
/*显示公交线路信息*/
#panel {
position: fixed;
background-color: white;
max-height: 90%;
overflow-y: auto;
top: 150px;
left: 240px;
width: 280px;
}
/*下面二个样式不知道为什么未生效,需要调整*/
#panel .amap-call {
background-color: #009cf9;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
#panel .amap-lib-walking {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
overflow: hidden;
}
</style>
页面效果展示:
点击查询按钮后结果在左上角呈现,这里可以看到罗盘控件有点遮挡结果,不需要罗盘控件可以把这个控件注释掉,或者把结果显示改到其他位置。
也可以点击其他线路进行查看。
到这里我想要的公交路线规划Demo已经实现了,等后面有需要直接使用和优化即可。