離線地圖----百度地圖2.0 轉自開源中國
鑑於許多人詢問百度地圖2.0怎麼搞?因為搞過1.3,所以感覺2.0應該也是不難搞的。因此本文整理一下2.0版離執行緒序的過程。
本過程完全基於1.3版的離執行緒序,因此許多資源如何下載就不重複了。瓦片都是一樣的,相關的檔案只有兩個:第一個是api主檔案,暫且命名apiv2.0.min.js吧,這樣和apiv1.3.min.js格式就完全一致了。另一個是模組外掛檔案,命名為getmodulesv2.0.js。
1. 下載api主檔案
api檔案的地址請訪問http://api.map.baidu.com/api?v=2.0。線上版使用該連結引入百度地圖的js,還需要增加一個ak引數,就是應用註冊時拿到的應用程式碼。這個程式碼是私有的,我就補貼出來了。事實證明無需這個程式碼能拿到主api檔案,並且是完全沒有問題的。
從這個地址拿到的是一段程式碼,裡面有一個連結,開啟它就能拿到api主檔案了。
2. 修改api主檔案
2.1 載入模組短路處理
搜尋下面的程式碼:“Pb(e.aG.MP+"&mod="+a.join(","))”,不包括兩端的中文引號
替換成為:“Pb("js/getmodules2.0.js")”
2.2 載入瓦片改為離線瓦片
搜尋下面的程式碼:”Uc.getTilesUrl“,不包括兩端的中文引號
將其實現改為:Uc.getTilesUrl=function(a,b,c){var x=a.x,y=a.y,e=1,z=b;return "tiles/"+z+"/"+x+"/"+y+".png";}
這時基本上就修改好了,只是還存在一個問題,就是非法呼叫的問題。
2.3 去掉ak驗證
ak驗證是通過jsonp來實現的,具體在哪裡呼叫的不清楚,但只要把jsonp工具移除就Ok了。
function Pb(a, b) { if (b) { var c = (1E5 * Math.random()).toFixed(0); z._rd["_cbk" + c] = function(a) { b && b(a); delete z._rd["_cbk" + c] }; a += "&callback=BMap._rd._cbk" + c } var d = K("script", { type : "text/javascript" }); d.charset = "utf-8"; d.src = a; d.addEventListener ? d.addEventListener("load", function(a) { a = a.target; a.parentNode.removeChild(a) }, q) : d.attachEvent && d.attachEvent("onreadystatechange", function() { var a = window.event.srcElement; a && ("loaded" == a.readyState || "complete" == a.readyState) && a.parentNode.removeChild(a) }); setTimeout(function() { document.getElementsByTagName("head")[0].appendChild(d); d = p }, 1) }
把這個方法找到,裡面的內容不解釋了,自己看吧。把裡面的程式碼都清空就O了。
修正!2.1步驟裡面呼叫了該方法載入模組程式碼,因此清空是不行的!執行沒問題,但擴充套件就不行了!改成這樣:
function Pb(a, b) {
if (/^http/.test(a))//這裡判斷一下,如果是呼叫外部資源就退出去好了
return;
if (b) {
var c = (1E5 * Math.random()).toFixed(0);
z._rd["_cbk" + c] = function(a) {
b && b(a);
delete z._rd["_cbk" + c]
};
a += "&callback=BMap._rd._cbk" + c
}
var d = K("script", {
type : "text/javascript"
});
d.charset = "utf-8";
d.src = a;
d.addEventListener ? d.addEventListener("load", function(a) {
a = a.target;
a.parentNode.removeChild(a)
}, q) : d.attachEvent
&& d.attachEvent("onreadystatechange", function() {
var a = window.event.srcElement;
a && ("loaded" == a.readyState || "complete" == a.readyState)
&& a.parentNode.removeChild(a)
});
setTimeout(function() {
document.getElementsByTagName("head")[0].appendChild(d);
d = p
}, 1)
};
向大家道歉!
2.4 本地工具資源的引用
搜尋“z.url.domain.main_domain_cdn.baidu[0]”,能夠找到z.ma的定義,將其置為空串即可。z.ma="";
2.5 去掉對blank.gif呼叫
搜尋“nb=o,setTimeout”,去掉對blank.gif的呼叫,把function體內的程式碼都清除即可,即:
function(a){a&&(nb=o,setTimeout(function(){}, 50))};
如果你要求不嚴格,這步可以不做。
3. 下載模組程式碼
從2.1步驟中可以知道,模組是通過一個連線下載下來的,再次訪問這個連線可以獲得一個js文件,命名為getmodules2.0.js丟到js資料夾中就行了。當然,2.1裡面怎麼寫,這裡就怎麼做。
這個地址大約是這樣的:
如果要擴充套件就得自己檢視模組路徑啦。
好了,其他的都還用1.3的內容。可能有一些擴充套件功能不相容,但總體上是一樣的。Enjoy it!
程式碼下載點選這裡
補記:
事情總是戲劇性發展,這是始料未及的。
我已開始研究這個2.0版本的時候,我在本地建立的資料夾是v2.0,然後一切很順利,跑起來也很正常。但是IE下一直不正常,我就繼續在研究(我主要用火狐,觀察比較方便)。結果發現,除了上面把載入模組的程式碼給錯誤的遮蔽了之外,如果我的程式碼拷貝到別的資料夾下就執行不正常,症狀和IE一樣。再進一步發現,v2.0這個資料夾改名為別的也出現這樣的錯誤。
一開始以為是快取的問題,清快取,還是不行,必須資料夾在我一開始的位置上,名字都不能變,改名就不行,換位置也不行。
經過進一步的跟蹤,發現問題出現在load方法上:
var load=function(a,b,c){
var d=this.gb(a);
if(d.Bd==this.Fj.Zp)
c&&b();
else{
if(d.Bd== this.Fj.hG){
this.bK(a);
this.jN(a);
var e=this;
e.zC==q&&(
e.zC=o,
setTimeout(function(){
for(var a=[],b=0,c=e.Md.En.length;b<c;b++){
var d=e.Md.En[b],l="";
ja.Gy.VJ(d)?l=ja.Gy.get(d):(l="",a.push(d+"_"+Qb[d]));
e.Md.Pv.push({DM:d,EE:l})
}
e.zC=q;
e.Md.En.length=0;
alert(a);//這裡很重要!幫助我們找到我們需要載入的模組!
0==a.length?e.LK():Pb("js/getmodules.js")
//這裡原先是:Pb(e.aG.MP+"&mod="+a.join(","))
},1)
);
d.Bd=this.Fj.vP
}
d.Pu.push(b)
}
}
問題就在於,a是一個數組,是統計到底哪些模組是沒有載入進來的,需要發起請求來到網路上去再載入。
好了,當目錄在我原先的v2.0裡面的時候,a陣列為空,並不需要再載入,因此呼叫的是e.LK(),這個方法到底幹了寫什麼,我也不清楚,太亂了。但是目錄換了,好傢伙,a陣列是一個好長的東西,長度15,是否會更長,我也不知道。
看到我alert一下了吧,在火狐底下是可以複製這個對話方塊裡面的內容的。然後把它放在步驟3給出的連線後面去下載這些程式碼,然後放在2.1裡面規定的js裡面,然後就一切搞定,IE下也表現正常了。這個檔案一下子膨脹到了433KB,真是恐怖啊!
後來收集了幾次,列出如下:
map_3uc0wi,scommon_ktwwno,mapclick_pispkz,oppc_kh0en0,vectordrawlib_o0famu,style_fcoka2,tile_5r2pa2,navictrl_vohbha,canvablepath_x52cuy,common_5w45zj,symbol_fwsijz,marker_25gtk1,draw_o13qo0,drawbysvg_wqhg4u,poly_qwgivy canvablepath_x52cuy,common_5w45zj,symbol_fwsijz,marker_25gtk1,draw_o13qo0,drawbysvg_wqhg4u,poly_qwgivy copyrightctrl_4v1wlk hotspot_41pssw
現在我仍然不明白,我的v2.0目錄咋就不需要這些東西呢?因為不需要,所以也就不載入getmodules.js裡面的內容了,這也導致擴充套件成問題了。到底什麼時候需要,什麼時候不需要呢?
好在這個載入過程是被動態呼叫的,就是你需要的時候才去載入。因此擴充套件的時候一定把功能跑全了,每彈出這個對話方塊的時候,都意味著要載入額外的程式碼。收集這些資訊,一次性載入到getmodules.js裡面就OK了。不會重複載入模組的。
為了相容IE9以下的版本,需要在demo.html裡面增加一句:
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
在此謝過@woodj