页面初始化时,加载百度地图JS,加载完成后执行回调函数开始定位,定位成功后初始化地图对象,计算导航路线,然后展示。
支持IP定位需要在页面标签引入的JS:
vue单文件组件:
mounted () {
this.loadBaiduMapAsync()
},
methods: {
/**
* 初始化百度地图并定位用户当前位置
*/
loadBaiduMapAsync() {
// 加载百度地图js
let script = document.createElement('script')
script.src = 'https://api.map.baidu.com/api?v=2.0&ak=申请的key&callback=initMap'
document.body.appendChild(script)
script.onload = (data) => { // 地图js加载成功
console.log('百度地图JS加载成功,开始定位')
window.initMap = this.startLocate
}
script.onerror = (data) => { // 地图js加载失败
console.log('百度地图JS加载失败,无法定位')
common.showConfirm('温馨提示','地图加载出错,请重试!', () => { this.loadBaiduMapAsync() }, null, '重新加载')
}
},
/**
* 获取用户当前定位 -- APP端端
*/
startLocate() {
if (this.isApp) { // APP端
this.getPositionByAPP().then(point => {
console.log('APP定位成功--位置:', point);
this.currPos = point
this.showMapAndGuide() // 展示地图及导航
}).catch(msg => {
this.status = 0
console.log(msg);
// common.showToast(msg, CONSTANTS.ERR_TOAST_TIME)
this.showDestination() // 展示地图和目的地
})
} else { // 浏览器端
this.getPositionByH5().then(point => {
console.log('浏览器定位成功--位置:', point);
this.currPos = point
this.showMapAndGuide() // 展示地图及导航
}).catch(msg => {
this.status = 0
console.log(msg);
// common.showToast(msg, CONSTANTS.ERR_TOAST_TIME)
this.showDestination() // 展示地图和目的地
})
}
},
/**
* 获取用户当前定位 -- APP端端
*/
getPositionByAPP() {
return new Promise(function(resolve, reject) {
const cb = (err, data) => {
if (err) {
if (err.code === '001') { // 未开启定位服务
reject('请检查您的定位服务是否开启')
} else if (err.code === '002') { // 未授权应用访问定位功能
reject('请授权APP访问您的位置信息')
} else {
console.warn(err);
reject('定位失败,位置信息不可用')
}
} else { // app定位成功
let point = {
longitude: data.Longitude,
latitude: data.Latitude
}
if (this.isiOS) { // IOS坐标转换
console.log('IOS坐标转换')
const convertor = new BMap.Convertor()
convertor.translate([new BMap.Point(point.longitude, point.latitude)], 1, 5, res => { // 经纬度转换,否则会定位不准
if (res.status === 0) {
point.latitude = res.points[0].lat
point.longitude = res.points[0].lng
resolve(point)
}
})
} else { // Andorid坐标
resolve(point)
}
}
}
app.getCurrentLocation(cb)
})
},
/**
* 获取用户当前定位 -- 浏览器端
*/
getPositionByH5() {
return new Promise(function(resolve, reject) {
const locateByIP = function () {
if (window.returnCitySN && window.returnCitySN.cip) { // 根据IP,通过百度api获得经纬度
console.log('returnCitySN:', window.returnCitySN);
$.getJSON("https://api.map.baidu.com/location/ip?callback=?", {
'ak' : '申请的百度地图key',
'coor' : 'bd09ll', // 百度经纬度坐标
'ip' : window.returnCitySN.cip // {cip: "116.77.145.35", cid: "440300", cname: "广东省深圳市"}
}, function(data) {
if (data && data.content) {
resolve({
longitude: data.content.point.x,
latitude: data.content.point.y
})
} else {
reject('定位失败,位置信息不可用')
}
})
}
}
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(pos) {
resolve({
longitude: pos.coords.longitude,
latitude: pos.coords.latitude
})
}, function(error) {
let msg = ''
switch(error.code) {
case error.PERMISSION_DENIED:
msg="用户拒绝对获取地理位置的请求。"
break;
case error.POSITION_UNAVAILABLE:
msg="位置信息是不可用的。"
break;
case error.TIMEOUT:
msg="请求用户地理位置超时。"
break;
case error.UNKNOWN_ERROR:
msg="未知错误。"
break;
}
reject(msg)
// console.warn('浏览器端(geolocation定位失败)-根据IP定位');
// locateByIP()
}, {
enableHighAccuracy: true, // 指示浏览器获取高精度的位置,默认为false
timeout: 5000, // 指定获取地理位置的超时时间,默认不限时,单位为毫秒
maximumAge: 2000 // 最长有效期,在重复获取地理位置时,此参数指定多久再次获取位置。
})
} else {
reject('定位失败,当前浏览器不支持定位!')
// console.warn('浏览器端(geolocation定位不支持)-根据IP定位');
// locateByIP()
}
})
},
/**
* 展示目标位置
*/
showDestination() {
if (Number.isNaN(this.lng)|| Number.isNaN(this.lat)) {
common.showAlert('地址参数错误!', CONSTANTS.ERR_TOAST_TIME)
return
}
// 展示地图
const map = new BMap.Map("allmap")
const endPos = new BMap.Point(this.urlParams.lng, this.urlParams.lat)
// 展示目标位置
this.status = 2
map.centerAndZoom(endPos, 16)
map.addOverlay(new BMap.Marker(endPos))
map.enableScrollWheelZoom(true)
// 在右上角添加缩放控件
const zoom = new BMap.NavigationControl({
anchor: BMAP_ANCHOR_TOP_RIGHT,
type: BMAP_NAVIGATION_CONTROL_LARGE,
enableGeolocation: true
})
map.addControl(zoom)
},
/**
* 展示地图并导航
*/
showMapAndGuide() {
if (Number.isNaN(this.lng)|| Number.isNaN(this.lat)) {
common.showAlert('页面地址参数错误!', CONSTANTS.ERR_TOAST_TIME)
return
}
// 展示地图
const map = new BMap.Map("allmap")
const startPos = new BMap.Point(this.currPos.longitude, this.currPos.latitude) // {lng: 114.02597366, lat: 22.54605355}
const endPos = new BMap.Point(this.lng, this.lat)
// 逆地址解析用户当前所在地址
const geoc = new BMap.Geocoder()
geoc.getLocation(startPos, res => {
const currCity = res.addressComponents.city // 用户当前定位所在城市
console.log(`定位城市:${currCity} -- 球场地址:${this.address}`);
if (this.cityName && this.cityName.indexOf(currCity) > -1) { // 用户和目标球场在同一城市
this.status = 1
map.centerAndZoom(startPos, 16)
this.driveRoute(map, startPos, endPos, true)
} else { // 用户和目标球场不在同一城市
this.status = 2
map.centerAndZoom(endPos, 16)
map.addOverlay(new BMap.Marker(endPos))
// this.driveRoute(map, startPos, endPos, true)
}
})
map.enableScrollWheelZoom(true)
// 在右上角添加缩放控件
const zoom = new BMap.NavigationControl({
anchor: BMAP_ANCHOR_TOP_RIGHT,
type: BMAP_NAVIGATION_CONTROL_LARGE,
enableGeolocation: true
})
map.addControl(zoom)
},
/**
* 计算驾驶路线
* @param startPos BMap.Point 起点位置
* @param endPos BMap.Point 终点位置
* @param show Boolean
*/
driveRoute(map, startPos, endPos, show) {
const DRIVE = new BMap.DrivingRoute(map, {
renderOptions: {
map: map,
autoViewport: show,
},
onSearchComplete: res => {
let plan = res.getPlan(0)
console.warn('查询驾车方案结果:', plan);
if (plan) {
this.driveDistance = plan.getDistance(true)
this.driveTime = plan.getDuration(true)
}
},
onMarkersSet: routes => {
// map.removeOverlay(routes[0].marker)
// map.removeOverlay(routes[1].marker)
// 解决百度地图起始点图标重叠问题
const eles = $('.BMap_Marker img')
if (eles.length > 0) {
eles.forEach(v => {
v.style.maxWidth = 'none'
v.style.width = '94px'
})
}
}
})
DRIVE.search(startPos, endPos)
}
}
}