上面是最终效果图。
一、爬取百度地图底图
OpenStreetMap提供的开源地图实在是不忍直视,所以爬取了百度地图的底图。网上爬取工具很多,就不过多赘述,我这里是使用node爬取,小巧快速。建议大家尝试。高清屏幕上展示建议爬取二倍图,以免显示效果不理想。百度服务器上的地图底图图片资源:
//百度服务器上的图片资源,尾部时间可根据需要修改,最好下载最新的
// tyles=pl,大字体ph,正常字体pl
// customid,地图样式,可选值:dark,midnight,grayscale,hardedge,light,redalert,googlelite,grassgreen,pink,darkgreen,bluish
let url = `http://online0.map.bdimg.com/tile/?qt=vtile&x=${i}&y=${j}&z=${z}&styles=pl&scaler=2&udt=20210411`;
我这里简单爬取公司附近的一小块区域:
二、在leaflet上显示百度地图瓦片
注意:leaflet和百度坐标系不一致,在加载百度瓦片时纠正百度地图瓦片坐标系为wgs84。 加载本地瓦片:
var normalMapUrl = 'http://localhost:8080/map/tiles1/{z}/{x}/{y}.png';
var normalMap = L.tileLayer(normalMapUrl, {
// subdomains: '0123456789',
maxZoom: 21,
minZoom: 3,
coordType: 'bd09',
tms: true,
});
//注意将map的crs赋值 crs: L.CRS.Baidu 详情请阅读示例页面
const map = L.map('map-container', {
crs: L.CRS.Baidu,
minZoom: 3,
maxZoom: 18,
attributionControl: false,
center: this.centerPos,
zoom: 18,
detectRetina: false,
layers: [normalMap],
contextmenu: true,
contextmenuItems: [
{
text: '设置为起点',
callback: this.setStartPoint,
},
{
text: '设置为中间点',
callback: this.setWaypoints,
},
{
text: '设置为终点',
callback: this.setStopPoint,
},
'-',
{
text: '开始规划',
callback: this.calcRoute,
},
],
});
三、本地搭建GraphHopper服务
- 前提:安装jdk1.8,java -version,查看是否安装成功
- 下载一个jar包,一个配置文件
wget https://graphhopper.com/public/releases/graphhopper-web-2.3.jar https://raw.githubusercontent.com/graphhopper/graphhopper/stable/config-example.yml
- 下载一份pbf格式的数据,我这里下载的是浙江省的路网数据
http://download.openstreetmap.fr/extracts/asia/china/
- 执行一条命令,由于数据过大,跑的时候可能出现内存问题,可以试试加上-Xmx2g -Xms2g
java -Xmx2g -Xms2g -Ddw.graphhopper.datareader.file=zhejiang-latest.osm.pbf -jar \*.jar server config-example.yml
- 服务启动之后,提示打开localhost:8989,后端搭建完毕。
四、leaflet前端请求后端GraphHopper服务
请求的完整链接,用代理解决跨域问题,route开头的路径代理到8989端口。
http://localhost:8080/route?point=30.280167196872135,120.00581735089507&point=30.28060382350749,120.01634549212933&type=json&locale=zh-CN&vehicle=car&weighting=fastest&points_encoded=false
axios发送请求
getRoute(url) {
/* url =
'route?point=30.27979217476267,120.00611188821497&point=30.27691993999111,120.01250627450645&type=json&locale=zh-CN&vehicle=car&weighting=fastest&points_encoded=false';
*/
axios.get(url).then(
res => {
console.log(res);
this._success(res);
},
err => {
console.log(err);
}
);
},
_success(res) {
var lnglats = res.paths[0].points.coordinates; //(lng,lat)
var latlngs = []; //(lat,lng)
for (let j = 0; j < lnglats.length; j++) {
var lnglat = lnglats[j];
var latlng = [];
latlng[0] = lnglat[1];
latlng[1] = lnglat[0];
latlngs.push(latlng);
}
var path = L.polyline.antPath(latlngs, { color: '#A52A2A', pulseColor: '#0000FF' });
path.addTo(this.map);
},
_buildRouteUrl() {
var allPoints = this._setPointsSequence();
if (allPoints == null || allPoints == undefined) {
return;
} else {
var locs = [],
i,
baseUrl;
for (i = 0; i < allPoints.length; i++) {
locs.push('point=' + allPoints[i].lat + ',' + allPoints[i].lng);
}
baseUrl = 'route?' + locs.join('&');
return baseUrl + '&type=json&locale=zh-CN&vehicle=car&weighting=fastest&points_encoded=false';
}
},
五、结束
为了满足公司核心业务需求,需要一整套离线地图相关的服务。目前还在探索中,期待和有相同需求的同学一起!