畢設(北斗導航項目)進行了一段時間,近日在實驗室給老師匯報進展時,由於網絡不暢,加載百度在線地圖及其各種操作時,時間過長,於是想將百度地圖離線化。查閱網上很多資料,有的是廣告(賣GIS應用的),有的版本太久......最后參考網上兩位前輩的博客內容,加以實踐,實現了地圖完全離線且能進行基本操作。趁周末整理了實踐過程並記錄下來,希望能幫到有需要的朋友。
注:感謝兩位前輩,其原文為:開源中國:Web版百度地圖加載離線瓦片 ;csdn:使用百度地圖JS API構建離線地圖應用(完整教程)
原文附帶Demo,大家可以參考下,注意版本:百度離線地圖Demo
具體實現步驟:
前期工作:構建在線地圖應用(版本API v1.3,其他版本未測試,如需要可自行研究)。
准備好放源碼的文件夾(可為中文),在其中建立三個文件夾:js、css、images,用於存放下面的文件。(基礎API下載地址:apiv1.3.min.js ;css文件下載地址:bmap.css )
先建立一個簡單的在線地圖應用,如下:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <title>DEMO</title> 6 <!--script type="text/javascript" src="js/apiv1.3.min.js"></script--> 7 <script type="text/javascript" src="http://api.map.baidu.com/api?v=1.3"></script> 8 <link rel="stylesheet" type="text/css" href="bmap.css"/> 9 </head> 10 <body> 11 <div style="width:520px;height:340px;border:1px solid gray" id="container"></div> 12 </body> 13 </html> 14 <script type="text/javascript"> 15 var map = new BMap.Map("container",{mapType: BMAP_NORMAL_MAP}); 16 var point = new BMap.Point(116.404, 39.915); // 創建點坐標 17 map.centerAndZoom(point,5); // 初始化地圖,設置中心點坐標和地圖級別。 18 19 //map.addControl(new BMap.MapTypeControl()); 20 map.addControl(new BMap.NavigationControl()); 21 map.enableScrollWheelZoom(); // 啟用滾輪放大縮小。 22 map.enableKeyboard(); // 啟用鍵盤操作。 23 </script>
以上代碼運行效果如圖:

觀察其向網絡請求的文件:(我使用的是Firefox瀏覽器的Firbug插件)

這些需離線的資源文件主要有三類:圖標素材、依賴模塊API文件、瓦片地圖文件,后面會寫到詳細步驟。
接下來,進入正式工作。
第一步:訪問前期工作中的第一個入口:http://api.map.baidu.com/api?v=1.3,其內容如下:
1 function(){window.wise=1;window.netSpeed=254;window.netType=1; window.BMap_loadScriptTime = (new Date).getTime(); 2 document.write('<script type="text/javascript" src="http://api.map.baidu.com/getscript?v=1.3&ak=&services=&t=20150527115231"></script>'); 3 document.write('<link rel="stylesheet" type="text/css" href="http://api.map.baidu.com/res/13/bmap.css"/>');})();
這一步將獲得一個js文件的位置和一個css文件的位置,然后分別下載下來,放在准備好的文件夾里面,我分別存儲在/js和/css里面。js的路徑后面有若干參數,不管,下載下來的文件重新命名就好,比如js文件命名為apiv1.3.min.js
第二步:修改這個js中的代碼。由於代碼是壓縮在一行上的,可通過網上的代碼在線格式化。
(我是使用了這個網站的工具JS/HTML/CSS格式化:http://tool.chinaz.com/tools/jsformat.aspx)
注意:修改文件的時候,建議與提供的Demo中的文件對比,並非全按以下的修改方式
1、搜索變量:“imgPath”,直到找到一段代碼
1 var x=m?"https://sapi.map.baidu.com/":"http://api.map.baidu.com/"; 2 var cd={imgPath:x+"images/",cityNames:{"\u5317\u4eac":"bj",
把imgPath:x+"images/"中的x去掉即可,這樣就變成了跟網絡地址無關的相對位置了。這里指出的images文件夾,是與將來的html文件夾平行的目錄里面的。
2、搜索變量:“_baseUrl”,直到找到這樣的一段代碼
preLoaded:{},Config:{_baseUrl:x+"getmodules?v=1.3",_timeout:5000},
同樣,要去掉x,這個x也是前面這段代碼中的x。同時,不僅要去掉x,更要把地址指向js目錄。
3、繼續搜索下一個“_baseUrl”,得到下面的代碼:
1 window.setTimeout(function(){var cP=cN.Config._baseUrl+"&mod="+cN.Module._arrMdls.join(",");cy.request(cP);cN.Module._arrMdls.length=0;cN.delayFlag=false},1)
直接修改cP變量,注意:這里把加載地址直接寫死
1 var cP=cN.Config._baseUrl+"modules";cy.request(cP);
這樣,我們把動態加載編程手動加載了。我們訪問這個地 址“http://api.map.baidu.com/getmodules?v=1.3&mod=map,oppc,tile,control,marker,poly”就可以拿到一個js文件了。把它重命名為上面指定的“modules”,丟在js文件夾里面即可。后面會詳細說明加載模塊這個問題。
注意:如果需要更多的功能,我是通過重新加載以上的地址,其它的教程寫說不需要自動加載,通過另外配置參數獲取相關的功能就好,我沒親自配置過,有配置過的小伙伴可以講講配置過程。
4、關鍵的一步:搜索“getTilesUrl”直到找到這樣的一段(參照物也可以另選,比如“BMAP_NORMAL_MAP”):
1 aU.getTilesUrl = function(cN, cQ) { 2 var cR = cN.x; 3 var cO = cN.y; 4 var T = "20150518"; 5 var cP = "pl"; 6 if (this.map.highResolutionEnabled()) { 7 cP = "ph" 8 } 9 var cM = j[Math.abs(cR + cO) % j.length] + "?qt=tile&x=" 10 + (cR + "").replace(/-/gi, "M") + "&y=" 11 + (cO + "").replace(/-/gi, "M") + "&z=" + cQ + "&styles=" + cP 12 + (a9.browser.ie == 6 ? "&color_dep=32&colors=50" : "") 13 + "&udt=" + T; 14 return cM.replace(/-(\d+)/gi, "M$1") 15 }; 16 window.BMAP_NORMAL_MAP = new cv("\u5730\u56fe", aU, { 17 tips : "\u663e\u793a\u666e\u901a\u5730\u56fe" 18 });
“getTilesUrl”這個方法,這里就是返回瓦片未知的關鍵方法。兩個參數中,第一個參數是{x,y},第二個參數就是z,這樣xyz就都有了。
直接把它計算出來的cM的結果重新計算一下,改成:
1 //這個地方廢棄了上面的計算結果,直接采用本地圖片 2 cM = "tiles/" + cQ + "/" + cR + "/" + cO + ".jpg";
開始建立第四個文件夾,tiles。這個文件夾里面的內容和后面的資源文件請在附件中下載。至於如何下載瓦片,問百度。至此,該文件的處理結束。
第三步:下載資源文件。(終於到資源文件的詳細介紹了,前期工作中提到)
1、圖片文件:可以通過前期工作的第二張圖的方式獲取素材的下載地址,也可從Demo文件/images路徑下獲取,還有一種方式,引用前輩教程中的話:
查找bmap.css里面所有的圖片文件,下載下來放在指定的文件夾里面就好了。里面總共不超過兩三個文件,下載下來放在 images文件夾里面就行了。另外,剛才的這個js里面也有一些資源文件,也下載下來放在images文件夾里面。這個通過搜索imgPath就能找 到,有png,有gif,有點文件可能需要通過https的地址才能下載的到。

得到基本的圖標素材后,將之前所下載的bmap.css文件里面圖片的url修改為本地路徑。
2、依賴模塊API文件(very very important!)
如果缺少某個依賴模塊,則無法使用相應的API。以下為引用前輩教程的原話:
這個請求文件的原理是根據你在自己頁面中使用的API來向官網請求相應的依賴模塊API,參數的字符串格式是根據所使用依賴模塊的順序生成“模塊名”以“,”分隔。
在運行前期工作中的在線地圖時,就可發現,依賴的庫參數是什么。例如:以下的代碼運行,所請求的依賴庫參數是http://api.map.baidu.com/getmodules?v=1.3&mod=map,oppc,tile,control
1 <script type="text/javascript"> 2 var map = new BMap.Map("container",{mapType:BMAP_NORMAL_MAP}); 3 var point = new BMap.Point(116.404, 39.915); // 創建點坐標 4 map.centerAndZoom(point,5); // 初始化地圖,設置中心點坐標和地圖級別。 5 6 //map.addControl(new BMap.MapTypeControl()); 7 map.addControl(new BMap.NavigationControl()); 8 map.enableScrollWheelZoom(); // 啟用滾輪放大縮小。 9 map.enableKeyboard(); // 啟用鍵盤操作。 10 //map.setCurrentCity("北京"); // 設置地圖顯示的城市 此項是必須設置的 11 </script>
我在自己操作過程中的依賴庫命名為modules(可修改,但與前面修改的JS文件要匹配),在Demo文件/js路徑下,里面已有map,oppc,tile,control,menu,marker,infowindow這些模塊,如第二步的第3小步所述,后期可根據需要重新下載,或重新配置,我是直接重新下載。

再強調一次,地址為:http://api.map.baidu.com/getmodules?v=1.3&mod=模塊名,根據自己需要,將內容添加到modules文件中,或重新下載,也可以全部下載下來放入modules文件中。
以下為前輩文章中提到的依賴模塊名稱、下載瓦片地圖文件方法。(我沒試過他的,有興趣的可嘗試)
1、所有依賴模塊名稱如下:(引前輩教程中的圖和內容,有誰知道這個圖是哪來的么?)
2、Demo文件中的modules文件中在map模塊部分已經去掉了百度版權信息
如有需要,可以直接使用此文件的map部分去除百度版權。
然后將此資源文件的請求路徑改為本地,需要在之前下載的apiv1.3.min.js中修改,由於細節較多這里就不詳細描述了,建議直接使用Demo文件中已修改好的apiv1.3.min.js文件。(如有興趣的話可以通過“代碼比較軟件”與之前下載apiv1.3.min.js進行比較找到修改之處)
3、下載瓦片地圖文件(tile)
這里提供一個下載瓦片地圖的軟件——全能電子地圖下載器1.9.5.zip ,里面包含有注冊機,安裝過程就不描述了。
這里是使用說明——使用說明(雖然軟件聲明能下載的地圖類型比較多,但好像只有百度地圖能正常使用)
根據自己需要下載瓦片地圖后直接拷貝到Demo文件/maptile路徑下(將原有的文件刪除)
最后:經歷了幾天,從查閱資料到完成初步的離線地圖的功能,和自己的軟件融合后,有些標注的功能還不太完善,如下圖,瓦片地圖因為沒注冊機,所以圖上很多廣告,且沒下載完整的瓦片地圖。暫時先總結了這部分離線操作,分享下自己的成果。

第一次寫博客,寫好久呀。。。^_^


