引子

最近一个WEB项目需求在纯局域网下显示设备定位,以前用惯了百度地图JS版 现在没外网了只有搞离线版了。百度官网是没有离线的JS版本,网上搜索了一圈下了不少评论中说好用的版本其中还花了十几块Down了个号称好用的。 本想着应该是妥妥的了,结果欠差人意,花钱的ZIP包中只有2个JS文件,其他的zip包里各种自己封装的JS和一些零星的地图瓦片。用基本都能用,问题集中在地图瓦片的获取上,于是在网上又找了不少瓦片下载工具,要么是过期下不到,要么是需要充钱才能用。最后聚焦在“斑马鱼”这款工具,1.免费2.功能也基本满足需求。 框选了个南京市大概范围 4-19级地图瓦片一共420多万个,软件提供50个线程同时下载 貌似不错 弄到凌晨5点多开下,一觉睡醒下午1点半。才下载了120多万条数据感觉有点懵逼 这下载速度有点鸡肋!!这玩不转啊,才只是一个南京市的瓦片的下载就需要这么长时间,要是搞几个省的,等这项目开始部署了瓦片也下不完呀。想办法提高瓦片下载的效率吧。

开搞、提速

研究了下“斑马鱼”,它有2个程序BMapTool.exe、BMapDown.exe。

BMapTool用来显示地图,框选下载区域,生成下载任务。

BMapDown读取下载任务,下载瓦片数据。

WinHex 打开生成的下载任务文件“xxxxx.tiles” 发现是个SQLite3数据库 里面3张表 task、tiles、zoom,从名字上看就知道各个表里是什么数据了。 再打开抓包工具看下瓦片是从哪下的,一目了然 URL是http://online3.map.bdimg.com/tile/?qt=vtile&x=6&y=1&z=5&styles=pl&scaler=1 其中参数 x y z 正好对应 tiles 表中 x y z 3个字段 那flag字段估计就是下载成功与否的标志位了。这下简单了所有需要下载的瓦片的URL都有了接下来就是提高下载工作的效率了的事了。“斑马鱼”下载慢主要原因应该是它对下载工作的调度的问题,还有就是本地网络下载速度的问题。

原因1:我在虚拟机里(win7 64位 2核)跑BMapDown下载数还一直跳个不停(网上下的EXE程序总是要先扔到虚拟机里跑下,抓下网络包看看它到底访问了什么网络,Procmon看下读取了哪些本地资源,看明白了才敢放在真机环境下跑)真机环境(win10 64位 16核)下载数下半天才跳一下。真机环境下载竟然比虚拟机慢一万倍,日了鬼了。

原因2:书房于客厅隔了两道墙WIFI信号不是满格。

解决方案:把下载工作直接扔到服务器上搞了事。下面是go写的瓦片下载程序,代码没多少,全贴出来。

dltiles.go

package mainimport ("bufio""database/sql""fmt"_ "github.com/mattn/go-sqlite3""io""net/http""os""time"
)//下载参数
type Job struct {Id   intUrl  stringPath stringFile string
}//下载结果参数
type Result struct {Id  intErr error
}//下载文件
func downFile(url string, path string, fn string) error {err := os.MkdirAll(path, 0777)if err != nil {fmt.Printf("Mkdir Error:%v\n", err)return err}fmt.Printf("Start Download %s\n", url)res, err := http.Get(url)if err != nil {fmt.Printf("Download URL:%s\tFail\n", url)return err}defer res.Body.Close()reader := bufio.NewReaderSize(res.Body, 64*1024)file, err := os.Create(path + fn)if err != nil {fmt.Printf("Create File:%s Fail Err:%v\n", path+fn, err)return err}writer := bufio.NewWriter(file)_, err = io.Copy(writer, reader)if err != nil {fmt.Printf("Write File:%s Fail Err:%v\n", path+fn, err)return err}fmt.Printf("%s -> %s OK\n", url, path+fn)return nil
}//------------------------------------------------------------------------------------//下载工作池
func DownloadPool(size int, jobChan chan *Job, retChan chan *Result) {for i := 0; i < size; i++ {go func(jobChan chan *Job, retChan chan *Result) {for job := range jobChan {err := downFile(job.Url, job.Path, job.File)r := &Result{Id:  job.Id,Err: err,}retChan <- r}}(jobChan, retChan)}
}//------------------------------------------------------------------------------------func checkErr(err error) {if err != nil {panic(err)}
}//用时统计
func timeCost(start time.Time) {tc := time.Since(start)fmt.Printf("Time total: %v\n", tc)
}func main() {//命令行参数处理if len(os.Args) < 3 {fmt.Println("dltiles [sqlite-file] [save-path]")os.Exit(0)}dbfile := os.Args[1]fmt.Printf("SQLite:%s\n", dbfile)path := os.Args[2]fmt.Printf("Save Path:%s\n", path)//准备下载工作jobChan := make(chan *Job, 256)retChan := make(chan *Result, 256)doneChan := make(chan int)DownloadPool(128, jobChan, retChan)t := time.Now()fmt.Printf("Time start: %s\n", t.Format("2006-01-02 15:04:05"))defer timeCost(t)//打开数据库db, err := sql.Open("sqlite3", dbfile)checkErr(err)//获取需要下载的瓦片数rows, err := db.Query("select count(*) as num from tiles")var Total introws.Next()rows.Scan(&Total)rows.Close()fmt.Printf("Total: %d\n", Total)//下载结果计数go func(retChan chan *Result, total int, done chan int) {var iDone intfor result := range retChan {if result.Err == nil {fmt.Printf("Job:%v Done\n", result.Id)} else {fmt.Printf("Job:%v Fail\t Err:%v\n", result.Id, result.Err)}iDone++if iDone == total {done <- 1}}}(retChan, Total, doneChan)//从sqlite取下载URLrows, err = db.Query("select * from tiles")checkErr(err)for rows.Next() {var id intvar flag intvar z intvar x intvar y interr = rows.Scan(&id, &flag, &z, &x, &y)checkErr(err)url := fmt.Sprintf("http://online3.map.bdimg.com/tile/?qt=vtile&x=%d&y=%d&z=%d&styles=pl&scaler=1", x, y, z)spath := fmt.Sprintf("%s/%d/%d/", path, z, x)sfn := fmt.Sprintf("%d.png", y)job := &Job{Id:   id,Url:  url,Path: spath,File: sfn,}jobChan <- job}db.Close()<-doneChan
}

使用方法:

服务器先安装go

wget https://golang.google.cn/dl/go1.17.5.linux-amd64.tar.gz

tar zxvf go1.17.5.linux-amd64.tar.gz

mv go /var/golang.17.5

rm go1.17.5.linux-amd64.tar.gz -rf

cd /usr/local/bin/

ln -s /var/golang.17.5/bin/go go

ln -s /var/golang.17.5/bin/gofmt gofmt

go env -w GO111MODULE=auto

然后下载SQLite依赖包

go get github.com/mattn/go-sqlite3

编译使用

go build dltiles.go

./dltiles xxx.ltiles(斑马鱼的SQLite任务文件) /download/tiles/(瓦片保存路径) >> tiles.log

或 直接 go run dltiles.go xxx.dltiles(斑马鱼的SQLite任务文件) /download/tiles/(瓦片保存路径) >> tiles.log

现在下载效率比PC上搞,快的起飞了420万多个瓦片 54分钟 搞定。

相关JS EXE 资源文中无法给出 给个链接 需要的哥们去下载吧。https://github.com/cnxbb/BaiduOfflineMap 题外话:现在的CSDN和以前的CSDN千差万别。什么JB玩意,发个帖子为了方便有同样需求的哥们们。

离线地图Demo

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no" name="viewport"/>
<title>Offline Map Demo</title>
<style type="text/css">body, html,#offlinemap, #tab, #mapfrm {width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微软雅黑";}#offlinemap {display:block;position:fixed;top:0px;left:0px;right:0px;bottom:0px;}
</style>
<script type="text/javascript" src="jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="baidumapv2/baidumap_offline_v2_load.js"></script>
<script language="JavaScript">var map;$(document).ready(function() {map = new BMap.Map("offlinemap");    // 创建Map实例map.centerAndZoom(new BMap.Point(116.404, 39.915), 5 );  // 初始化地图,设置中心点坐标和地图级别map.enableScrollWheelZoom(true);     //开启鼠标滚轮缩放map.addControl(new BMap.NavigationControl());   //缩放按钮map.setMinZoom(5);//设置最小缩放等级//添加个大头针var point = new BMap.Point( 116.404, 39.915 );var dicon = new BMap.Icon( "mapding_red.png", new BMap.Size( 22, 40 ) );var mk = new BMap.Marker( point, { icon: dicon, offset: new BMap.Size(0, -20 ) } );setTimeout( function() {map.panTo( point );}, 200 );map.addOverlay( mk );});
</script>
</head>
<body style="padding:0px;margin:0px;"><div id="offlinemap"></div>
</body></html>

百度离线地图 2023年1月7日相关推荐

  1. QT实现加载百度离线地图

    在Qt中加载百度地图需要用到网络浏览器,在此采用webEngine模块,然后用webchannel进行qt与HTML/JavaScript的交互. 需求描述:软件加载百度地图,用鼠标在地图上选点,并进 ...

  2. 百度离线地图开发,node实现地图瓦片下载

    最近有个Web项目要用离线地图,项目是在内网环境,找了很多资料,踩了很多坑,好在已经实现了,下面把资料整理一下. 首先是百度离线地图开发包,原文地址是http://www.xiaoguo123.com ...

  3. web百度离线地图开发(详细教程)2019

    web百度离线地图开发(详细教程) 需求情景 主要参考 开发步骤 一.JS API文件下载 二.修改API文件 1.屏蔽ak验证 2.设置引用本地资源路径 3.下载本地资源 4.引用本地资源 三.加载 ...

  4. 如何用百度离线API调用百度离线地图

    这里以广西南宁市为例,说明如何用百度离线API调用百度离线地图. 首先,点击视图左上方的地图类型按钮选择百度地图(如果没有该项请点击"更多"选项),然后在视图右上方选择广西省南宁市 ...

  5. 百度离线地图示例之三:矢量图

    前言介绍: 主要是基于v3.0的API版本进行的离线,纯内网可操作,基本上实现了现有90%以上的功能点,能兼容jpg和png格式的瓦片图层,实现了原生和基于Vue两个版本(包含常用的55个示例),文末 ...

  6. vue2+百度离线地图实现多车辆行驶动态轨迹

    vue2+百度离线地图实现行驶多车辆动态轨迹 实现多多车辆实时轨迹监控,每个10秒监测一次接口,进行动态追加.(前端实现,如果数量庞大的车辆移动,很消耗性能) 百度离线地图引入方法查看: vue项目实 ...

  7. 百度离线地图示例之四:热力图

    前言介绍: 主要是基于v3.0的API版本进行的离线,纯内网可操作,基本上实现了现有90%以上的功能点,能兼容jpg和png格式的瓦片图层,实现了原生和基于Vue两个版本(包含常用的55个示例),文末 ...

  8. 百度离线地图示例之二:测距

    前言介绍: 主要是基于v3.0的API版本进行的离线,纯内网可操作,基本上实现了现有90%以上的功能点,能兼容jpg和png格式的瓦片图层,实现了原生和基于Vue两个版本(包含常用的55个示例),文末 ...

  9. 百度离线地图 —— 瓦片地图下载

    百度离线地图使用 下载工具,工具在文末. 解压,打开文件夹,找到 BaiDuMapTile.exe 应用程序,双击打开,下载瓦片地图. 下载完之后,有一个maptile文件夹,就是所需区域的瓦片地图 ...

最新文章

  1. 16条很有用的Chrome浏览器命令
  2. AIphaCode 并不能取代程序员,而是开发者的工具
  3. WCF技术剖析之二十五: 元数据(Metadata)架构体系全景展现[WS标准篇]
  4. 请人安装linux系统,我想安装linux操作系统,请指导一下
  5. UFLDL深度学习笔记 (三)无监督特征学习
  6. SQL Tuning 基础概述01 - Autotrace的设定
  7. 判断点在直线的哪一侧_点与线、线与线、距离这些一锅煮,你能否顺利消化
  8. 前端学习(1907)vue之电商管理系统电商系统之渲染修改用户的表单的重置操作
  9. 水晶报表-控制结构-For 循环(Crystal 语法)
  10. 常见的div盒子居中(上下左右)实现
  11. 任正非回应退休传闻;董明珠谈直播首秀“失败”;Wine 5.7 发布​| 极客头条...
  12. android 笔记本推荐 2015年,IDC:Android平板份额2015年将超iPad
  13. C#入门详解(10)
  14. 第8章 多项式回归与模型泛化 学习笔记上
  15. 【HDU - 3038】How Many Answers Are Wrong 【带权并查集 - 向量偏移】
  16. 推荐程序员收藏的几个技术社区以及工具网站
  17. linux安装iscsi设备,linux系统下安装配置iSCSI教程
  18. 如何高效优雅地下载CMIP6模式数据
  19. flutter集成高德地图获取位置
  20. 【PCB专题】PCB板卡上的UL标识是什么?

热门文章

  1. 南京邮电大学2019-2020第二学年度微型计算机接口技术考试真题回忆
  2. rsync linux yum,使用rsync搭建centos的镜像站
  3. 2023美国大学生数学建模竞赛中文题目发布
  4. html5 websocket c++,C++ websocket库 websocketpp/websocket++例子编译试用
  5. 基于EmguCv圆形答题卡识别的优化
  6. “对DllRegisterServer的调用失败,错误代码为0×80070005 ”
  7. 使用JDK的JAXB将XML转化为JAVA对象,原生支持
  8. vue-barcode生成条形码
  9. 你的流量卡是快递激活还是自主激活?看看派送的快递就知道了!
  10. Matlab app 实现键盘按键和鼠标单击按钮一样的功能