最近有个Web项目要用离线地图,项目是在内网环境,找了很多资料,踩了很多坑,好在已经实现了,下面把资料整理一下。
首先是百度离线地图开发包,原文地址是http://www.xiaoguo123.com/p/baidumap_offline_v21
这是数据包-百度离线地图API V2.1
里面有在线地图的基本API,可以满足绝大部分需求,不行的在自己扩展,附两张目录结构图
项目所需的两个入口文件,其他按正常百度地图API开发即可
之后就是瓦片地图的下载,也就是文件夹tiles,里面是百度地图的底图瓦片目录,下面贴上我的下载代码
var request = require('request') // 用于请求瓦片地图
var fs = require("fs"); // 文件操作
var bagpipe = require('bagpipe') // 用于异步请求数量控制
var TileLnglatTransform = require('tile-lnglat-transform'); // 用于经纬度转换为瓦片坐标
var x1 = 120.128465, y1 = 30.393577 // 起始点坐标(左上角)
var x2 = 120.708555, y2 = 29.914415 // 终点坐标(右下角)
// 根据地图平台使用转换类
var TileLnglatTransformBaidu = TileLnglatTransform.TileLnglatTransformBaidu;
var all = [] // 保存所有层级瓦片坐标等信息
for(i = 3; i <= 18; i++){
all[i] = {}
p1 = TileLnglatTransformBaidu.lnglatToTile(x1, y1, i)
p2 = TileLnglatTransformBaidu.lnglatToTile(x2, y2, i)
all[i].t = i // 层级
all[i].x = [p1.tileX, p2.tileX] // 瓦片横坐标范围(左至右)
all[i].y = [p2.tileY, p1.tileY] // 瓦片纵坐标范围(下至上)
}
// console.log(all)
var bag = new bagpipe(100, {timeout: 1000}) //限制请求数,此处为100,可根据网络情况修改
var path = './tiles' // 瓦片目录
fs.access(path, fs.constants.F_OK, err => {
// 创建tiles文件夹
if (err) fs.mkdir(path, err => {})
for (let z = 3; z <= all.length - 1; z++) {
fs.access(`${path}/${z}`, fs.constants.F_OK, err => {
// 创建tiles/Z文件夹 ,Z是层级
if (err) fs.mkdir(`${path}/${z}`, err => {})
for (let x = all[z].x[0]; x <= all[z].x[1]; x++) {
fs.access(`${path}/${z}/${x}`, fs.constants.F_OK, err => {
// 创建tiles/Z/X文件夹 ,X是瓦片横坐标
if (err) fs.mkdir(`${path}/${z}/${x}`, err => {})
})
}
})
}
// 文件夹可能较多,等待1s开始下载
setTimeout(() => {
task()
}, 1000)
})
function task() {
for (let z = 3; z <= all.length - 1; z++) {
for (let x = all[z].x[0]; x <= all[z].x[1]; x++) {
for (let y = all[z].y[0]; y <= all[z].y[1]; y++) {
// 将下载任务推入队列,bag会以100张为单位批量下载
bag.push(download, x, y, z)
}
}
}
}
function download(i, j, z) {
// url是百度服务器上的图片资源,尾部时间可根据需要修改,最好下载最新的
let url = `http://online0.map.bdimg.com/tile/?qt=tile&x=${i}&y=${j}&z=${z}&styles=pl&scaler=1&udt=20180711`
request({url, timeout: 4000}, (err, res, body) => {
if (err) {console.log(err)}
}).pipe(fs.createWriteStream(`${path}/${z}/${i}/${j}.png`));
}
这里引用了两个包,一个BagPipe用来限制并发,一个tile-lnglat-transform用来转换坐标
部分用法在代码注释里有,详细的可参考他们的项目。图片量较大,上图是杭州市萧山区3到18级瓦片总共8W+png,约300M。
19级加上的话要30W+png,没敢下有点多。。。
之后就是将下载好的tiles文件夹覆盖到项目目录下,目录结构第二张的tiles文件夹,
这里再提供一个好用的瓦片下载器
至此,离线地图基本完成,愉快的开发吧!