web百度离线地图开发(详细教程)
需求情景
主要参考
开发步骤
一、JS API文件下载
二、修改API文件
1、屏蔽ak验证
在 bmap_offline_api_min.js 文件中,用 Math.random() 多找几次,定位到下列代码位置:
(以下代码方法名称和一些变量名称可能会有出入,我下载的代码就和网上一些贴子上看到的代码不尽相同)
function oa(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) };
然后修改上面的代码,对http拦截,不进行外部访问,只需在最开始加一行代码if (/^http/.test(a)) return;
function oa(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、设置引用本地资源路径
在 bmap_offline_api_min.js 文件中,用 url.domain.main_domain_cdn.baidu[0] 多找几次,定位到下面的代码:
z.url = z.Y_[z.Qy]; z.wp = z.url.proto + z.url.domain.baidumap + "/"; z.wc = z.url.proto + ("2" == z.Qy ? z.url.domain.main_domain_nocdn.other: z.url.domain.main_domain_nocdn.baidu) + "/"; z.ma = z.url.proto + ("2" == z.Qy ? z.url.domain.main_domain_cdn.other[0] : z.url.domain.main_domain_cdn.baidu[0]) + "/"; z.cj = z.url.proto + z.url.domain.main_domain_cdn.webmap[0] + "/"; z.rg = function(a, b) {
var c, d, b = b || ""; switch (a) {
case "main_domain_nocdn": ...
然后将 z.cj = z.url.proto + z.url.domain.main_domain_cdn.webmap[0] + "/" 改为 z.cj = '' :
z.url = z.Y_[z.Qy]; z.wp = z.url.proto + z.url.domain.baidumap + "/"; z.wc = z.url.proto + ("2" == z.Qy ? z.url.domain.main_domain_nocdn.other: z.url.domain.main_domain_nocdn.baidu) + "/"; z.ma = z.url.proto + ("2" == z.Qy ? z.url.domain.main_domain_cdn.other[0] : z.url.domain.main_domain_cdn.baidu[0]) + "/"; //!!!!!!!!!!!!!!!!!!!!!!! z.cj = ''; //!!!!!!!!!!!!!!!!!!!!!!! z.rg = function(a, b) {
var c, d, b = b || ""; switch (a) {
case "main_domain_nocdn": ...
3、下载本地资源
所谓本地资源,就是在使用地图时需要用到的一些模块(module),比如图层类,标记类,控件类。
当你在地图中用到这些模块时,它会自动加载,因此我们需要先把这些模块的js文件下载下来,保存到本地。
这些模块有几十个之多,我们这里并不都存本地,而是用到哪个下载哪个,那么如何知道用到了哪个模块呢?
- 首先,在
bmap_offline_api_min.js文件中,用&mod=定位到下面的代码,然后加一行代码将用到的模块打印出来:
load: function(a, b, c) {
var d = this.ib(a); if (d.Bd == this.Fj.cq) c && b(); else {
if (d.Bd == this.Fj.pG) {
this.lK(a); this.zN(a); var e = this; e.DC == q && (e.DC = o, setTimeout(function() {
for (var a = [], b = 0, c = e.Pd.Fn.length; b < c; b++) {
var d = e.Pd.Fn[b], l = ""; ia.Ly.fK(d) ? l = ia.Ly.get(d) : (l = "", a.push(d + "_" + Rb[d])); e.Pd.Tv.push({
TM: d, KE: l }) } e.DC = q; e.Pd.Fn.length = 0; //!!!!!!!!!!!!!!!!!!!! console.log(a); //!!!!!打印所需模块,这很重要 //!!!!!!!!!!!!!!!!!!!! 0 == a.length ? e.XK() : oa(e.iG.$P + "&mod=" + a.join(",")) 0 == a.length ? e.UK() : Qb("js/getmodules2.0.js") }, 1)); d.Bd = this.Fj.JP } d.Ru.push(b) } },
- 然后,我们在需要使用地图的vue页面里,按照官方文档正常使用:(具体功能去官网找dome示例即可)
mounted(){
this.$nextTick(() => {
// 百度地图 var map = new BMap.Map("container"); var point = new BMap.Point(106., 29.); map.centerAndZoom(point, 12); //设置定位点的弹跳动画 var marker = new BMap.Marker(point); // 创建标注 map.addOverlay(marker); // 将标注添加到地图中 marker.setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画 map.enableScrollWheelZoom(true); //添加工具条比例尺控件 var top_left_control = new BMap.ScaleControl({
anchor: BMAP_ANCHOR_TOP_LEFT});// 左上角,添加比例尺 var top_left_navigation = new BMap.NavigationControl(); //左上角,添加默认缩放平移控件 var top_right_navigation = new BMap.NavigationControl({
anchor: BMAP_ANCHOR_TOP_RIGHT, type: BMAP_NAVIGATION_CONTROL_SMALL}); //右上角,仅包含平移和缩放按钮 map.addControl(top_left_control); map.addControl(top_left_navigation); map.addControl(top_right_navigation); }) },
特别注意:如果你要在进入页面就初始化地图,最好像上面那样,放在 mounted 生命函数的 this.$nextTick(() => {}) 里,以确保地图容器 #container 元素渲染完成,不然有可能因为初始化时地图容器还未渲染而报错:

刷新这个vue页,关注控制台,就能看到要实现这些地图功能所需要的模块名,是个数组集合,如下图,我这里需要”control_ff1mc0″, “navictrl_wxtn3y”两个模块:

- 这样获得模块文件
这个链接 http://api0.map.bdimg.com/getmodules?v=2.0&t=20140707&mod=infowindow_omcokh,将其中 &mod= 之后的参数替换成我们打印出来的模块名,比如:
http://api0.map.bdimg.com/getmodules?v=2.0&t=20140707&mod=control_ff1mc0
http://api0.map.bdimg.com/getmodules?v=2.0&t=20140707&mod=navictrl_wxtn3y
分别访问上述链接,就可以看到模块文件代码:
- 在static文件夹下新建modules文件夹来存放即将下载的模块文件:

新建以模块名命名的js文件,将模块文件代码粘贴到响应模块js文件里。这样需要的模块文件就下载好了。有几个模块下载几个文件:

4、引用本地资源
在上面步骤打印模块名的地方,做如下修改:
load: function(a, b, c) {
var d = this.ib(a); if (d.Bd == this.Fj.cq) c && b(); else {
if (d.Bd == this.Fj.pG) {
this.lK(a); this.zN(a); var e = this; e.DC == q && (e.DC = o, setTimeout(function() {
for (var a = [], b = 0, c = e.Pd.Fn.length; b < c; b++) {
var d = e.Pd.Fn[b], l = ""; ia.Ly.fK(d) ? l = ia.Ly.get(d) : (l = "", a.push(d + "_" + Rb[d])); e.Pd.Tv.push({
TM: d, KE: l }) } e.DC = q; e.Pd.Fn.length = 0; console.log(a); //!!!!!!打印所需模块 // 0 == a.length ? e.XK() : oa(e.iG.$P + "&mod=" + a.join(",")) // 0 == a.length ? e.UK() : Qb("js/getmodules2.0.js") // !!!!!!!!!!!!!!!!!!!!!!!!引用本地下载好的模块文件资源 if( a.length > 0 ){
for(let i=0; i<a.length;i++){
let mf = './static/modules/'+a[i]+'.js'; oa( mf ); console.log('加载模块文件:'+mf); //IE error } } else {
e.XK() } // !!!!!!!!!!!!!!!!!!!!! }, 1)); d.Bd = this.Fj.JP } d.Ru.push(b) } },
三、加载瓦片改为本地离线瓦片
离线瓦片可以理解为地图离线包,没有它,离线地图是无法显示的。
1、存储目录
首先,在 static 目录下新建文件夹 tiles 来存放瓦片:

2、下载瓦片
用水经注或者太乐地图下载器下载瓦片,我用太乐。
选择百度

下载 -> 选择行政区划,选完了之后该区域就会出现ufo图标

点击图标,选择 地图:

选择直接保存瓦片后,存储标准选择百度瓦片,存储格式会自动选择 .png。然后选择级别之后确定即可:
级别就是调用百度地图api处设置的缩放级别:

下载完成后可在这里查看:
找到存储目录:我这里下载了重庆12级的瓦片,所有的瓦片就存储在了12这个文件夹下

将12这个文件夹整个复制到项目static/tiles目录下

你会发现除了下载了12级,还下载了9、10、11级,因为离线的关系,在地图上进行缩放操作到11级,但是如果没有11级的瓦片,地图就什么都不显示。所以如果想要缩放多少级,这些级别的瓦片必须都下载到本地。
3、瓦片配置文件
static目录下新建mp_load.js文件,定义瓦片路径及瓦片格式即地图api的主目录:

我们的瓦片是png格式的:
var bmapcfg = {
'imgext' : '.png', //瓦片图的后缀 根据需要修改,一般是 .png .jpg 'tiles_dir' : '', //普通瓦片图的地址,为空默认在tiles/ 目录 }; var scripts = document.getElementsByTagName("script"); var JS__FILE__ = scripts[scripts.length - 1].getAttribute("src"); //获得当前js文件路径 bmapcfg.home = JS__FILE__.substr(0, JS__FILE__.lastIndexOf("/")+1); //地图API主目录
4、修改加载瓦片路径
在 bmap_offline_api_min.js 文件中,可以用 getTilesUrl 多找几次,定位到下面代码:
Yc.getTilesUrl = function(a, b, c) {
var d = a.x, a = a.y, e = Qb("normal"), f = 1, c = Xc[c]; this.map.Ix() && (f = 2); d = this.map.eb.Bw(d, b).ds; return (Wc[Math.abs(d + a) % Wc.length] + "?qt=vtile&x=" + (d + "").replace(/-/gi, "M") + "&y=" + (a + "").replace(/-/gi, "M") + "&z=" + b + "&styles=" + c + "&scaler=" + f + (6 == x.da.la ? "&color_dep=32&colors=50": "") + "&udt=" + e).replace(/-(\d+)/gi, "M$1") }
修改如下:
Yc.getTilesUrl = function(a, b, c) {
var d = a.x, a = a.y, e = Qb("normal"), f = 1, c = Xc[c]; // this.map.Ix() && (f = 2); // d = this.map.eb.Bw(d, b).ds; // return (Wc[Math.abs(d + a) % Wc.length] + "?qt=vtile&x=" + (d + "").replace(/-/gi, "M") + "&y=" + (a + "").replace(/-/gi, "M") + "&z=" + b + "&styles=" + c + "&scaler=" + f + (6 == x.da.la ? "&color_dep=32&colors=50": "") + "&udt=" + e).replace(/-(\d+)/gi, "M$1") //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! let tdir = bmapcfg.tiles_dir.length>0?bmapcfg.tiles_dir:bmapcfg.home + "tiles"; console.log(tdir + "/" + b + "/" + d + "/" + a + bmapcfg.imgext) return tdir + "/" + b + "/" + d + "/" + a + bmapcfg.imgext; // 使用本地的瓦片 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! };
这里在 mp_load.js 里已经取到了主路径,可以将之前加载模块(三 – 4)处代码修改成:(不修改也可)

四、关于离线
五、关于地图下载器
1、免费/付费
- 太乐
太乐地图下载器在没有付费的情况下,最高只能下载12级,而且文件数量有限制,也就是说如果你选择的区域很大,可能连12级都无法下载,比如这里,我要下载中国地图,只能下载到第8级:

而且下载下来的瓦片会有很大很夸张的水印:

但是,如果你买了vip,那就没有任何限制了,具体收费情况我没问 - 水经注
我没用水经注来说明,是因为水经注下载器,如果没有付费,下载不了瓦片。水经注的购买费用大概800元,买了后没有限制,一直可用。
2、瓦片文件的大小
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/226602.html原文链接:https://javaforall.net
