鉴于许多人询问百度地图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
问题就在于,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_qwgivycanvablepath_x52cuy,common_5w45zj,symbol_fwsijz,marker_25gtk1,draw_o13qo0,drawbysvg_wqhg4u,poly_qwgivycopyrightctrl_4v1wlkhotspot_41pssw
现在我仍然不明白,我的v2.0目录咋就不需要这些东西呢?因为不需要,所以也就不加载getmodules.js里面的内容了,这也导致扩展成问题了。到底什么时候需要,什么时候不需要呢?
好在这个加载过程是被动态调用的,就是你需要的时候才去加载。因此扩展的时候一定把功能跑全了,每弹出这个对话框的时候,都意味着要加载额外的代码。收集这些信息,一次性加载到getmodules.js里面就OK了。不会重复加载模块的。
为了兼容IE9以下的版本,需要在demo.html里面增加一句:
在此谢过@woodj