1. 程式人生 > >離線地圖----百度地圖2.0 轉自開源中國

離線地圖----百度地圖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