J2EE 项目总结
- JavaScript API GL v1.0 是目前版本最新的百度地图 API,相比于 JavaScript API v3.0 界面更加美观,功能更加强大。
# 项目需求
- 从后端读取起点和终点的地址,在地图上显示两者之间的路径。
- 获得路径上所有点的坐标,用以显示卡车的虚拟位置。
# 具体实现
# 解析地址
- 从官方文档中可以得到示例代码:
var map = new BMapGL.Map('container'); | |
// 创建地址解析器实例 | |
var myGeo = new BMapGL.Geocoder(); | |
// 将地址解析结果显示在地图上,并调整地图视野 | |
myGeo.getPoint('北京市海淀区上地10街', function (point) { | |
if (point) { | |
map.centerAndZoom(point, 16); | |
map.addOverlay(new BMapGL.Marker(point, { title: '北京市海淀区上地10街' })) | |
} else { | |
alert('您选择的地址没有解析到结果!'); | |
} | |
}, '北京市') |
- 分析代码可以得知:
getPoint
函数用以将地址字符串解析为Point
,并通过回调函数进一步对 Point 进行处理。
# 显示路径
- 获得路径可以有多种选择,例如:驾车路线,步行路径,公交路径,骑行路径等等。百度也提供了货车路径的规划,但需要向百度递交申请,过程较为繁琐,所以最终考虑选择使用驾车路线规划。
- 从官方文档中可以得到示例代码:
var map = new BMapGL.Map("container"); | |
map.centerAndZoom(new BMapGL.Point(116.404, 39.915), 11); | |
var p1 = new BMapGL.Point(116.301934, 39.977552); | |
var p2 = new BMapGL.Point(116.508328, 39.919141); | |
var driving = new BMapGL.DrivingRoute(map, { renderOptions: { map: map, autoViewport: true } }); | |
driving.search(p1, p2); |
- 分析代码可以得知:
search
函数用以获得p1
,p2
两个坐标之间的路径 - 将以上两个示例代码结合可以很自然的想到以下代码:
var map = new BMapGL.Map("container"); | |
map.centerAndZoom(new BMapGL.Point(116.404, 39.915), 11); | |
var myGeo = new BMapGL.Geocoder(); | |
var p1, p2; | |
myGeo.getPoint('北京市海淀区上地10街', function (point) { | |
if (point) { | |
p1 = point; | |
} else { | |
alert('您选择的地址没有解析到结果!'); | |
} | |
}) | |
myGeo.getPoint('北京市海淀区颐和园路5号', function (point) { | |
if (point) { | |
p2 = point; | |
} else { | |
alert('您选择的地址没有解析到结果!'); | |
} | |
}) | |
var driving = new BMapGL.DrivingRoute(map, { renderOptions: { map: map, autoViewport: true } }); | |
driving.search(p1, p2); |
- 但实际上以上代码是不能运行的,在 search 函数被调用之前输出
p1
和p2
可以发现两者都是undefined
。这是因为getPoint
函数其实是异步函数,执行顺序并非按照顺序执行,所以会导致无法对p1
和p2
赋值。所以改变策略,考虑使用函数嵌套的手段进行赋值:
var map = new BMapGL.Map("container"); | |
map.centerAndZoom(new BMapGL.Point(116.404, 39.915), 11); | |
var myGeo = new BMapGL.Geocoder(); | |
myGeo.getPoint('北京市海淀区上地10街', function (point) { | |
if (point) { | |
var p1 = point; | |
myGeo.getPoint('北京市海淀区颐和园路5号', function (point) { | |
if (point) { | |
var p2 = point; | |
var driving = new BMapGL.DrivingRoute(map, { renderOptions: { map: map, autoViewport: true } }); | |
driving.search(p1, p2); | |
} else { | |
alert('您选择的地址没有解析到结果!'); | |
} | |
}) | |
} else { | |
alert('您选择的地址没有解析到结果!'); | |
} | |
}) |
- 经测试,可以正常运行:
# 获取坐标
- 获得坐标在官方文档中并没有相关的代码供参考,所以只能自行解决。
- 网络上许多和获取路径上坐标的代码多为:
driving.search(p1, p2); | |
var pts = driving.getResults().getPlan(0).getRoute(0).getPath(); |
- 但这实际上是无法运行的,会显示
Cannot read property 'getPlan' of undefined
: - 在查看了计算驾车距离和时间的相关示例代码后可以知道在
DrivingRoute
中参数renderOptions
可以传入一个回调函数完成对route
结果的处理,即:
var p2 = point; | |
var searchComplete = function (results) { | |
if (driving.getStatus() != BMAP_STATUS_SUCCESS) { | |
return; | |
} | |
// 对结果的处理,可以使用 getPlan 函数了 | |
var plan = results.getPlan(0).getRoute(0).getPath(); | |
} | |
var driving = new BMapGL.DrivingRoute(map, { | |
renderOptions: { map: map, autoViewport: true }, | |
onSearchComplete: searchComplete, | |
}); | |
driving.search(p1, p2); |
- 以上代码可以成功输出,返回结果为一个数组,包含路径上所有点的经纬度:
- 可以使用
Marker
在地图上标注点的位置:
var marker1 = new BMapGL.Marker(new BMapGL.Point(plan[i].lng, plan[i].lat)); | |
map.addOverlay(marker1); |
# 完整代码
function generateMap(sendAddress, receiveAddress, createTime, status) { | |
var map = new BMapGL.Map("container"); | |
var myGeo = new BMapGL.Geocoder(); | |
myGeo.getPoint(sendAddress, function (point) { | |
if (point) { | |
var p1 = point; | |
map.centerAndZoom(point, 16); | |
myGeo.getPoint(receiveAddress, function (point) { | |
if (point) { | |
var p2 = point; | |
var searchComplete = function (results) { | |
if (driving.getStatus() != BMAP_STATUS_SUCCESS) { | |
return; | |
} | |
var plan = results.getPlan(0).getRoute(0).getPath(); | |
if (status == "ON_THE_WAY") { | |
var len = plan.length - 1; | |
var now = parseInt(Date.now() / 1000); | |
var time1 = Date.parse(createTime) / 1000; | |
var i = parseInt((now - time1) / 259200 * len); | |
if (i > len) i = len; | |
var marker1 = new BMapGL.Marker(new BMapGL.Point(plan[i].lng, plan[i].lat)); | |
map.addOverlay(marker1); | |
} | |
} | |
var driving = new BMapGL.DrivingRoute(map, { | |
renderOptions: { map: map, autoViewport: true }, | |
onSearchComplete: searchComplete, | |
}); | |
driving.search(p1, p2); | |
} else { | |
alert('收货地址没有解析到结果!'); | |
} | |
}) | |
} else { | |
alert('发货地址没有解析到结果!'); | |
} | |
}) | |
map.enableScrollWheelZoom(true); // 开启鼠标滚轮缩放 | |
var scaleCtrl = new BMapGL.ScaleControl(); // 添加比例尺控件 | |
map.addControl(scaleCtrl); | |
var zoomCtrl = new BMapGL.ZoomControl(); // 添加比例尺控件 | |
map.addControl(zoomCtrl); | |
var navi3DCtrl = new BMapGL.NavigationControl3D(); // 添加 3D 控件 | |
map.addControl(navi3DCtrl); | |
} |