百度地图、高德地图中心点设置和路径规划
a.前期准备
引入bmap.js文件
- 获取js文件,浏览器输入url:
http://api.map.baidu.com/api?v=3.0&ak=你的ak
- 对应输入百度ak,并复制标黄的部分在浏览器打开,将其中的内容复制到bmap.js文件中
b.地图组件主要代码
- index.vue文件
<template>
<div :id="id" class="map-container"></div>
</template>
<script>
import { getDrivingRoute, getCityPosition, getBdDrivingRoute, getBdCityPosition } from "./api/index";
import { mapGetters } from "vuex";
export default {
name: "ZitMap",
props: {
id: {
type: String,
default: "map-container",
},
amapServerURL: String,
bmapServerURL: String,
amapKey: String,
bmapBsKey: String,
bmapKey: String,
amapServiceKey: String,
bmapServiceKey: String,
secureKey: String,
startPos: {
type: Array,
default: () => [],
},
endPos: {
type: Array,
default: () => [],
},
},
data() {
return {
map: null,
polyline: null,
ambulMarker: null,
hospitalMarker: null,
timer: null,
ambulIcon: require("./assets/img/ambul2.png"),
hospitalIcon: require("./assets/img/hospital2.gif"),
};
},
computed: {
...mapGetters("settings", ["webConfig"]),
},
watch: {
startPos() {
console.log('起点变化了');
this.clearMap();
if(this.webConfig.MAP_USE == 0){
console.log(this.startPos,this.endPos,'起点终点高德经纬度111');
this.createAMapMarkers();
this.drawAMapRoute();
}else if(this.webConfig.MAP_USE == 1){
console.log(this.startPos,this.endPos,'起点终点百度经纬度111');
this.createBMapMarkers();
this.drawBMapRoute();
}
// this.drawRoute();
},
},
mounted() {
this.loadMapJS();
},
beforeDestroy() {
this.destroyMap();
},
methods: {
// 动态加载地图 JS 文件
loadMapJS() {
if (this.webConfig.MAP_USE == 0) {
this.loadAMapJS();
} else if (this.webConfig.MAP_USE == 1) {
this.loadBMapJS();
}
},
// 加载高德地图 JS 文件
loadAMapJS() {
window.amapServerURL = this.amapServerURL.replace(/(https?:\/\/)/, "");
window.amapKey = this.amapKey;
window._AMapSecurityConfig = {
securityJsCode: this.secureKey,
};
this.loadJS(() => {
this.initAMap();
}, "/js/amap/amap.js?v=" + Date.now());
},
// 加载百度地图 JS 文件
loadBMapJS() {
window.bmapKey = this.bmapKey; //浏览器端密钥,用来初始化地图
window.bmapBsKey = this.bmapBsKey; // 服务端密钥,用来获取中心点和获取路径规划
this.loadJS(() => {
this.initBMap();
}, "/js/bmap/bmap.js?v=" + Date.now());
},
// 初始化高德地图,设置传入的城市为地图中心点(如果后面有路径规划,则设置路径规划为地图中心点)
async initAMap() {
try {
const cityData = await getCityPosition(this.webConfig.CITY, this.amapServiceKey);
const location = cityData.geocodes[0].location.split(",");
this.map = new window.AMap.Map(this.id, {
zoom: 10,
});
if (location) {
this.map.setZoomAndCenter(10, location);
}
this.createAMapMarkers();
this.drawAMapRoute();
} catch (error) {
console.error("高德地图初始化失败:", error);
}
},
// 初始化百度地图,设置传入的城市为地图中心点(如果后面有路径规划,则设置路径规划为地图中心点)
async initBMap() {
try {
const cityData = await getBdCityPosition(this.webConfig.CITY, this.bmapKey);
const location = cityData.result.location;
// this.map = new window.Map(this.id);
this.map = new BMapGL.Map(this.id, {
zoom: 10,
});
this.map.centerAndZoom(new window.BMapGL.Point(location.lng, location.lat), 10);
this.map.enableScrollWheelZoom(true)
this.createBMapMarkers();
this.drawBMapRoute();
} catch (error) {
console.error("百度地图初始化失败:", error);
}
},
// 创建高德地图标记
createAMapMarkers() {
this.ambulMarker = this.createAMapMarker({
width: 40,
height: 40,
lng: this.startPos[0] || 116.481028,
lat: this.startPos[1] || 39.989643,
image: this.ambulIcon,
});
this.hospitalMarker = this.createAMapMarker({
width: 40,
height: 40,
lng: this.endPos[0] || 116.465302,
lat: this.endPos[1] || 40.004717,
image: this.hospitalIcon,
});
},
// 创建百度地图标记
createBMapMarkers() {
console.log(this.endPos,this.startPos,'百度终点起点坐标');
this.ambulMarker = this.createBMapMarker({
width: 40,
height: 40,
lng: this.startPos[0] || 116.481028,
lat: this.startPos[1] || 39.989643,
image: this.ambulIcon,
});
this.hospitalMarker = this.createBMapMarker({
width: 40,
height: 40,
lng: this.endPos[0] || 116.465302,
lat: this.endPos[1] || 40.004717,
image: this.hospitalIcon,
});
},
// 绘制路线
drawRoute() {
if (this.webConfig.MAP_USE == 0) {
this.drawAMapRoute();
} else if (this.webConfig.MAP_USE == 1) {
this.drawBMapRoute();
}
},
// 绘制高德地图路线
async drawAMapRoute() {
if (!this.map || this.startPos.length < 2 || this.endPos.length < 2) {
return;
}
try {
const res = await getDrivingRoute(
this.startPos.join(","),
this.endPos.join(","),
this.amapServiceKey
);
const {
route: { paths },
} = res;
const { distance, duration, steps } = paths[0];
this.$emit('complete',{distance,duration});
const pathList = steps
.map(({ polyline }) => polyline.split(";"))
.flatMap((step) => step.map((item) => new window.AMap.LngLat(...item.split(","))));
if (this.polyline) {
this.map.remove(this.polyline);
}
this.polyline = new window.AMap.Polyline({
path: pathList,
borderWeight: 2,
strokeColor: "green",
lineJoin: "round",
});
this.ambulMarker.setPosition(new window.AMap.LngLat(...this.startPos));
this.hospitalMarker.setPosition(new window.AMap.LngLat(...this.endPos));
this.map.add([this.polyline, this.ambulMarker, this.hospitalMarker]);
// 路径规划设置为视野中心
this.map.setFitView([this.polyline], true, [5, 5, 5, 5], 17);
this.$emit("done", distance, duration);
} catch (error) {
console.error("高德地图路线绘制失败:", error);
}
},
// 绘制百度地图路线
async drawBMapRoute() {
if (!this.map || this.startPos.length < 2 || this.endPos.length < 2) {
return;
}
try {
const startJWD = [this.startPos[1],this.startPos[0]];
const endJWD = [this.endPos[1],this.endPos[0]];
const res = await getBdDrivingRoute(
startJWD.join(","),
endJWD.join(","),
this.bmapKey
);
const { result: { routes } } = res;
const { distance, duration, steps } = routes[0];
this.$emit('complete',{distance,duration});
const pathList = steps
.map(({ path }) => path.split(";"))
.flatMap((step) => step.map((item) => new window.BMapGL.Point(...item.split(","))));
if (this.polyline) {
this.map.removeOverlay(this.polyline);
}
console.log(pathList)
this.polyline = new window.BMapGL.Polyline(pathList, {
strokeColor: "green",
strokeWeight: 2,
strokeOpacity: 1,
});
// this.ambulMarker.setPosition(new window.BMapGL.Point(...this.startPos));
// this.hospitalMarker.setPosition(new window.BMapGL.Point(...this.endPos));
this.map.addOverlay(this.polyline);
this.map.addOverlay(this.ambulMarker);
this.map.addOverlay(this.hospitalMarker);
const polyCenter = [new BMapGL.Point(this.startPos[0],this.startPos[1]),new BMapGL.Point(this.endPos[0],this.endPos[1])];
// 路径规划设置为视野中心
this.map.setViewport(polyCenter,{
enableAnimation: true,
margins: [10, 10, 10, 10]
});
this.$emit("done", distance, duration);
} catch (error) {
console.error("百度地图路线绘制失败:", error);
}
},
// 创建高德地图标记
createAMapMarker({ width = 40, height = 40, lng = "", lat = "", image, label = "" }) {
const icon = new window.AMap.Icon({
size: new window.AMap.Size(width, height),
image,
imageSize: new window.AMap.Size(width, height),
});
const marker = new window.AMap.Marker({
position: new window.AMap.LngLat(lng, lat),
offset: new window.AMap.Pixel(-width / 2, -height / 2),
icon,
title: "",
});
if (label) {
marker.setLabel({
offset: new window.AMap.Pixel(0, -15),
content: `<div class="amap-marker-label">${label}</div>`,
});
}
return marker;
},
// 创建百度地图标记
createBMapMarker({ width = 40, height = 40, lng = "", lat = "", image, label = "" }) {
const icon = new window.BMapGL.Icon(image, new window.BMapGL.Size(width, height));
const pt = new window.BMapGL.Point(lng, lat)
const marker = new window.BMapGL.Marker(pt, { icon });
if (label) {
const labelOpts = {
offset: new window.BMapGL.Size(0, -15),
content: `<div class="bmap-marker-label">${label}</div>`,
};
marker.setLabel(labelOpts);
}
return marker;
},
// 清理地图
clearMap() {
if (this.map) {
if (this.webConfig.MAP_USE == 0) {
this.polyline && this.map.remove(this.polyline);
this.ambulMarker && this.map.remove(this.ambulMarker);
this.hospitalMarker && this.map.remove(this.hospitalMarker);
this.map.clearMap();
} else if (this.webConfig.MAP_USE == 1) {
this.polyline && this.map.removeOverlay(this.polyline);
this.ambulMarker && this.map.removeOverlay(this.ambulMarker);
this.hospitalMarker && this.map.removeOverlay(this.hospitalMarker);
this.map.clearOverlays();
}
}
},
// 销毁地图
destroyMap() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
if (this.map) {
this.map.destroy();
this.map = null;
}
},
// 动态加载 JS 文件
loadJS(callback, url) {
let script = document.createElement("script");
script.type = "text/javascript";
script.readyState
? (script.onreadystatechange = (e) => {
const { readyState } = script;
if (readyState == "loaded" || readyState == "complete") {
callback && callback();
script.onreadystatechange = null;
}
})
: (script.onload = (e) => {
callback && callback();
});
script.onerror = (e) => {
this.mapError = true;
this.$message({
showClose: true,
message: "地图加载失败!",
type: "error",
duration: 5000,
});
console.log(e);
};
script.src = url;
document.body.appendChild(script);
},
},
};
</script>
<style scoped>
.map-container {
width: 100%;
height: 100%;
flex: 1;
}
</style>
- api/index.js文件
import axios from "@network";
/**
*
* @param {*} origin eg. 116.481028,39.989643
* @param {*} destination eg. 116.465302,40.004717
* @param {*} key eg. 336200d534d6e0303b0267cf1f11c5af
* @returns
*/
export const getDrivingRoute = (origin, destination, key) => {
const url = `/PROXY_AMAP/direction/driving`;
return axios.get(url, {
params: {
origin,
destination,
key,
extensions: 'all',
output: 'json',
}
});
}
export const getCityPosition = (address, key) => {
const url = `/PROXY_AMAP/geocode/geo`;
return axios.get(url, {
params: {
address,
key,
output: 'json',
}
});
}
// 百度
export const getBdDrivingRoute = (origin, destination, ak) => {
const url = `/PROXY_BDMAP/direction/v2/driving`;
return axios.get(url, {
params: {
origin,
destination,
ak
}
});
}
export const getBdCityPosition = (address, ak) => {
const url = `/PROXY_BDMAP/geocoding/v3`;
return axios.get(url, {
params: {
address,
ak,
output: 'json',
}
});
}
c.调用地图组件
<template>
<div style="margin-top:50px">
<el-collapse v-model="activeNames" class="collapse">
<el-collapse-item name="1" class="collapse-item">
<template slot="title">
<div class="text-xl">实时定位</div>
</template>
<div class="container">
<div class="show">
<div class="distance-wrapper">
<div class="distance">预估距离</div>
<div class="distance-value">
<span class="value">
{{ distance?distance:'未知' }}
</span>
<span class="unit">km</span>
</div>
</div>
<div class="split"></div>
<div class="duration-wrapper">
<div class="duration">预计用时</div>
<div class="duration-value">
<span class="value">
{{ minutes?minutes:'未知' }}
</span>
<span class="unit">分</span>
<span class="value" style="margin-left: 10px">
{{ seconds?seconds:'未知' }}
</span>
<span class="unit">秒</span>
</div>
</div>
</div>
<div class="map" id="map-container">
<zit-map
:startPos="ambulPos"
:endPos="hospitalPos"
:amapServerURL="webConfig.serverURL"
:bmapServerURL="webConfig.serverURL"
:amapKey="webConfig.AMAP_KEY"
:bmapKey="webConfig.DEFAULT_BDBSMAP_AK"
:bmapBsKey="webConfig.DEFAULT_BDMAP_AK"
:amapServiceKey="webConfig.AMAP_SERVICE_KEY"
:secureKey="webConfig.SECUREKEY"
@complete="getTimeAndDis"
></zit-map>
</div>
</div>
</el-collapse-item>
</el-collapse>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import { findTaskDetail } from "@api/warning-info";
export default {
name: "RealTimeLocation",
// props: {
// ambulOutInfo: {
// type: Array,
// required: true,
// },
// videoInfo: {
// type: Array,
// required: true,
// },
// },
components: {
ZitMap,
CommonVideo,
HaikangVideo,
HaikangVideoNew,
TopBar,
},
data() {
return {
ambulOutInfo: {},
videoInfo: [],
activeNames: ["1", "2", "3"],
ambulPos: [],
hospitalPos: [],
time:"",
minutes:"",
seconds:"",
distance:""
};
},
computed: {
...mapGetters("settings", ["webConfig", "serverConfig"]),
mounted() {
this.findTaskDetail('20250207010001000006');// 为了获取经纬度
},
methods: {
getTimeAndDis({distance: dis, duration: dur}){
this.minutes = this.formatMinute(dur);
this.seconds = this.formatSecond(dur);
this.distance = this.formatDistance(dis);
},
// 时间转换
formatMinute(time){
const minute = Math.floor(time / 60);
return minute;
},
formatSecond(time){
const second = Math.floor(time % 60);
return second;
},
// 距离转换
formatDistance(distance){
return `${(distance / 1000).toFixed(1)}`;
},
async findTaskDetail(lsh) {
const warnTaskDetail = await findTaskDetail({
lsh,
});
this.ambulOutInfo = warnTaskDetail.lst_ambul_out; // 获取经纬度,为空的话写死一个以供测试
const ambuJd = this.ambulOutInfo[0].ccsjJd?this.ambulOutInfo[0].ccsjJd:118.796624;
const ambuWd = this.ambulOutInfo[0].ccsjWd?this.ambulOutInfo[0].ccsjWd:32.059344;
const hosJd = this.ambulOutInfo[0].ccsjJd?this.ambulOutInfo[0].ccsjJd:116.322056;
const hosWd = this.ambulOutInfo[0].ccsjWd?this.ambulOutInfo[0].ccsjWd:39.89491;
this.ambulPos = [ambuJd, ambuWd];
this.hospitalPos = [hosJd,hosWd];
},
};
</script>
<style lang="scss" scoped>
.show {
position: absolute;
display: flex;
align-items: center;
// top: 3px;
background-color: #fff;
z-index: 999;
border-radius: 20px;
width: 78%;
height: 80px;
left: 40%;
transform: translate(-50%, 0);
border-radius: 5px;
background: linear-gradient(180deg, #ffeeee 0%, #f7bdbd 100%);
box-sizing: border-box;
box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px,
rgba(60, 64, 67, 0.15) 0px 2px 6px 2px;
.distance-wrapper,
.time-wrapper,
.duration-wrapper {
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
line-height: 30px;
}
.distance {
font-size: 16px;
color: #833636;
font-weight: bold;
}
.distance-value {
font-size: 32px;
color: #833636;
font-weight: bold;
}
.value {
margin-right: 10px;
font-size: 45px;
font-family: "led regular";
}
.unit {
font-size: 16px;
color: #833636;
font-weight: bold;
}
.split {
width: 0;
height: 0;
margin-right: -1px;
border-left: 30px solid transparent;
border-bottom: 80px solid #fc8080;
}
.split_own {
width: 0;
height: 0;
margin-right: -1px;
border-right: 30px solid transparent;
border-top: 80px solid #fc8080;
}
.arrival {
font-size: 16px;
color: #000;
font-weight: bold;
}
.arrival-value {
font-size: 32px;
color: #000;
font-weight: bold;
}
.duration-wrapper {
background-color: #fc8080;
// border-radius: 5px;
margin-right: -1px;
border-bottom-left-radius: 0;
.duration {
font-size: 16px;
color: #fff;
font-weight: bold;
}
.duration-value {
font-size: 32px;
color: #fff;
font-weight: bold;
}
// 单位
.unit {
font-size: 16px;
color: #fff;
font-weight: bold;
}
}
}
.collapse {
width: 100%;
font-size: 28px;
margin-top: 20px;
.collapse-item {
width: 100%;
}
.text-xl {
font-size: 20px;
font-weight: bold;
color: #3891a0;
margin-left: 15px;
}
}
.container {
display: flex;
height: 620px;
width: 98%;
.map {
width: 80%;
// height: 738px;
margin: 88px 0px 0px 12px;
}
}
</style>
d.成果展示
- 百度地图
- 高德地图
需要注意的是,有时候坐标并不是直接可以使用的,需要进行坐标系的转换,这个后续有空再记录……