1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > vue--百度地图之离线地图

vue--百度地图之离线地图

时间:2024-09-10 10:46:51

相关推荐

vue--百度地图之离线地图

一、为什么有离线地图的存在

项目要在局域网内使用,也就是我们所说的在内网中使用,无法连接外网,所以需要开发离线地图功能。

(在看以下步骤前,先提示这个vue项目是vue-cli生成的,并且你需要确保你的在线地图是成功的,在线地图如果不知道怎么做,可以看我另一篇博客:在线地图)

二、离线百度地图开发步骤

其实理解了离线百度地图,它的使用很简单,就是把在线百度地图的一些js文件下载到本地,再引用一下就可以啦

1、获取百度地图api的js代码

访问此链接

http://api./api?v=3.0&ak=biuHZmoAow03mjwThwt8f2whaf4mVdHf

这里特别注意一下,不是说直接用这个链接,这里只是给出了步骤,你需要将ak替换为你自己的(申请ak,点击这里),再进行如下步骤!!!

多说一句:申请ak时选择浏览器端哦!!!

打开会看到以下内容

在代码中找到红框中的内容

src=http://api./getscript?v=3.0&ak=biuHZmoAow03mjwThwt8f2whaf4mVdHf&services=&t=1018171908

打开src中的链接,就可以获得百度地图api的js代码

2、js代码格式化,保存

在代码格式化工具中,将上面的代码格式化,以便查看和修改。

-08-04 更新start:这里代码格式化可以直接在浏览器上进行,步骤如图

-08-04 更新end

然后新建js文件,将格式化后的代码粘贴进去,命名为baidu-api.js

再然后将此js文件放在vue项目中,我的放在了static下

最后,在vue项目的启动入口index.html的head中引入这个js文件

3、修改百度地图API文件

3.1 下载本地资源

所谓本地资源,就是在使用地图时需要用到的一些模块(module),比如图层类,标记类,控件类。

当你在地图中用到这些模块时,它会自动加载,因此我们需要先把这些模块的js文件下载下来,保存到本地。

这些模块有几十个之多,我们这里并不都存本地,而是用到哪个下载哪个,那么如何知道用到了哪个模块呢?

首先,在 baidu-api.js 文件中,用 &mod= 定位到下面的代码,然后加一行代码将用到的模块打印出来:

load: function(a, b, c) {var e = this.ob(a);if (e.Le == this.Bj.Mp) c && b();else {if (e.Le == this.Bj.bG) {this.UJ(a);this.hN(a);var f = this;f.fC == t && (f.fC = p, setTimeout(function() {for (var a = [], b = 0, c = f.Qd.fn.length; b < c; b++) {var e = f.Qd.fn[b],n = "";ia.oy.PJ(e) ? n = ia.oy.get(e) : (n = "", a.push(e + "_" + Bc[e]));f.Qd.Cv.push({zM: e,rE: n})}f.fC = t;f.Qd.fn.length = 0;console.log("打印所需模块") console.log(a)//打印所需模块,这很重要!!!!!!//console.log(f.TF.IP)//打印下面一行oa()里面的值,你需要通过这个链接下载模块---08-04// 0 == a.length ? f.DK() : oa(f.TF.IP + "&mod=" + a.join(","))//引用本地下载好的模块文件资源if (a.length > 0) {for (let i = 0; i < a.length; i++) {let mf='./static/modules/'+a[i]+'.js'//let mf = bmapcfg.home + 'modules/' + a[i] + '.js';oa(mf);console.log('加载模块文件:' + mf) //IE error}} else {f.DK()//这里的函数DK(),根据你上面注释的那一行函数名而定}},1));e.Le = this.Bj.xP}e.yu.push(b)}},

3.2 在baidu-api.js文件中,用Math.random()全局查找几次(我的是第5次),定位到以下代码位置:

(以下代码会在百度更新有些出入,但基本样式不变,找相似)

function oa(a, b) {if (b) {var c = (1E5 * Math.random()).toFixed(0);D._rd["_cbk" + c] = function(a) {b && b(a);delete D._rd["_cbk" + c]};a += "&callback=BMap._rd._cbk" + c}var e = L("script", {type: "text/javascript"});e.charset = "utf-8";e.src = a;e.addEventListener ? e.addEventListener("load",function(a) {a = a.target;a.parentNode.removeChild(a)},t) : e.attachEvent && e.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(e);e = q},1)};

到此步,默认你已找到!!!

然后修改上面的代码,对HTTP拦截,不进行外部访问,只需在最开始添加一行:

if (/^http/.test(a)) return; //如果是调用外部资源就退出去

如下:

function oa(a, b) {//添加一行,对http拦截,不进行外部访问///if (/^http/.test(a)) return; //如果是调用外部资源就退出去-.7.29//这里的a其实就是3.1步骤中oa(mf)里的mf,即你下载的模块路径--08-04/if (b) {var c = (1E5 * Math.random()).toFixed(0);D._rd["_cbk" + c] = function(a) {b && b(a);delete D._rd["_cbk" + c]};a += "&callback=BMap._rd._cbk" + c}var e = L("script", {type: "text/javascript"});e.charset = "utf-8";e.src = a;e.addEventListener ? e.addEventListener("load",function(a) {a = a.target;a.parentNode.removeChild(a)},t) : e.attachEvent && e.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(e);e = q},1)};

3.3 设置引用本地资源路径

在baidu-api.js文件中,用url.domain.main_domain_cdn全局多查找几次,定位到下面的代码:

D.Zt = window.HOST_TYPE || "0";D.url = D.s0[D.Zt];D.ep = D.url.proto + D.url.domain.baidumap + "/";D.nd = D.url.proto + ("2" == D.Zt ? D.url.domain.main_domain_nocdn.other: D.url.domain.main_domain_nocdn.baidu) + "/";D.oa = D.url.proto + ("2" == D.Zt ? D.url.domain.main_domain_cdn.other[0] : D.url.domain.main_domain_nocdn.baidu) + "/";D.Yi = D.url.proto + D.url.domain.main_domain_cdn.webmap[0] + "/";

然后将

D.Yi = D.url.proto + D.url.domain.main_domain_cdn.webmap[0] + “/”;

改为 D.Yi = ‘’ ;

如下:

D.Zt = window.HOST_TYPE || "0";D.url = D.s0[D.Zt];D.ep = D.url.proto + D.url.domain.baidumap + "/";D.nd = D.url.proto + ("2" == D.Zt ? D.url.domain.main_domain_nocdn.other: D.url.domain.main_domain_nocdn.baidu) + "/";D.oa = D.url.proto + ("2" == D.Zt ? D.url.domain.main_domain_cdn.other[0] : D.url.domain.main_domain_nocdn.baidu) + "/";// D.Yi = D.url.proto + D.url.domain.main_domain_cdn.webmap[0] + "/";D.Yi = '';

然后,我们在需要使用地图的vue页面里,按照官方文档正常使用:

<template><div id='MapBox'><div class='baiduMap' id='mapShow' ref="mapShow"></div></div></template><script>export default {name:'baiduMap',data() {return{map: undefined,overView: undefined,marker: undefined,BMap: undefined,}},methods:{baiduMap(){debuggerthis.BMap = BMap;// 创建地图实例this.map = new BMap.Map("mapShow");// 创建点坐标let point = new BMap.Point(118.8035, 32.0658);//创建标注this.marker=new BMap.Marker(point);//缩略地图控件。this.overView=new BMap.OverviewMapControl({isOpen: true});//添加控件this.map.addControl(this.overView);//添加一个标注this.map.addOverlay(this.marker);// 初始化地图,设置中心点坐标和地图级别this.map.centerAndZoom(point, 12);//this.map.setCurrentCity("南京");//开启鼠标滚轮缩放this.map.enableScrollWheelZoom(true);}},mounted(){this.$nextTick(() => {this.baiduMap();})}}</script><style>#MapBox {width: 100%;height: 100%;padding: 10px;position: relative;}/* 地图 */.baiduMap{height: 100%;width: 100%;}/* 去除地图上,左下字体标注 */.anchorBL{display:none;}</style>

特别注意:如果你要在进入页面就初始化地图,最好像上面那样,放在 mounted 生命函数的 this.$nextTick(() => {})里,以确保地图容器 #mapShow 元素渲染完成,不然有可能因为初始化时地图容器还未渲染而报错:

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

通过下面的地址,只需要更换mod后面的值就可以找到需要的模块

下载api依赖模块的地址:点击这里下载依赖模块

-08-04 更新start

可能有些小伙伴通过上面的链接获取到的是空,这里更新下

在3.1步骤中,你可以看到这样一句话

0 == a.length ? f.DK() : oa(f.TF.IP + "&mod=" + a.join(","))

f.TF.IP打印出来,在后面加上&mod=,后面再加上你要下载的模块名称即可

-08-04 更新end

在static下建一个modules文件夹来存放即将下载的模块文件

然后新建以打印出的模块为命名的js,将通过地址搜索到的js复制到此js文件里。这样模块文件就下载好了。

现在就能成功加载模块资源了。

这里要注意路径问题,如果路径不对,找不到模块文件,会报错:

三、加载瓦片改为本地离线瓦片

离线瓦片可以理解为地图离线包,没有它,离线地图无法显示的。

1、瓦片嵌入在项目中的应用

1.1下载瓦片

太乐地图下载器----由于我电脑目前装不上这个软件,没有亲自下载,该过程暂时省略,后续会补上的哈

这里就先默认小伙伴们都已经拿到离线地图的图片资源了!!!

将所有瓦片文件夹整个复制到项目static/tiles目录下

因为离线的关系,在地图上进行缩放操作,想要缩放多少级,这些级别的瓦片必须都下载到本地。

1.2 瓦片配置文件

static目录下新建map_load.js文件,定义瓦片路径及瓦片格式即地图api的主目录:

我的瓦片是png格式的:

var bmapcfg={'imgext':'.png',//瓦片图的后缀 根据需要修改 一般.jpg .png'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主目录,我这里打印出来为./static/

然后,在vue项目的启动入口index.html的head中引入map_load.js文件,要在baidu-api.js文件之前引入该配置文件:

1.3 修改baidu-api.js文件,加载瓦片路径

在 baidu-api.js 文件中,可以用 getTilesUrl 多找几次,定位到下面代码:

pe.getTilesUrl = function(a, b, c) {var e = a.x,a = a.y,f = Tb("normal"),g = 1,c = oe[c];this.map.lx() && (g = 2); e = this.map.$e.fw(e,b).Zl; return (ne[Math.abs(e + a) % ne.length] + "?qt=vtile&x=" + (e + "").replace(/-/gi,"M") + "&y=" + (a + "").replace(/-/gi, "M") + "&z=" + b + "&styles=" + c + "&scaler=" + g + (6 == A.fa.na ? "&color_dep=32&colors=50" : "") + "&udt=" + f + "&from=jsapi3_0").replace(/-(\d+)/gi,"M$1")};

修改如下:

pe.getTilesUrl = function(a, b, c) {var e = a.x,a = a.y,f = Tb("normal"),g = 1,c = oe[c];// this.map.lx() && (g = 2); // e = this.map.$e.fw(e,b).Zl; // return (ne[Math.abs(e + a) % ne.length] + "?qt=vtile&x=" + (e + "").replace(/-/gi,"M") + "&y=" + (a + "").replace(/-/gi, "M") + "&z=" + b + "&styles=" + c + "&scaler=" + g + (6 == A.fa.na ? "&color_dep=32&colors=50" : "") + "&udt=" + f + "&from=jsapi3_0").replace(/-(\d+)/gi,"M$1")//加载本地瓦片-.7.29let tdir = bmapcfg.tiles_dir.length > 0 ? bmapcfg.tiles_dir: bmapcfg.home + "tiles";console.log(tdir + '/' + b + '/' + e + '/' + a + bmapcfg.imgext);return tdir + '/' + b + '/' + e + '/' + a + bmapcfg.imgext; //使用本地的瓦片//};

在这里可将调用瓦片的地址打印出来看看是否正确:

如果瓦片存在,且路径正确,就能正常显示地图了。

地图不能显示出来,是瓦片相关有问题

(看看是不是自己定的地图中心点坐标不在离线地图范围内,这时候会报错找不到图片)

地图的功能不能实现,是模块相关有问题

(看看模块资源是否齐全,关注打印区域,会有相关提示哦,ps:我最初没有加模块文件,客户端直接调试时谷歌浏览器都没报错,相关功能也全部正常;但放到nginx中就凉啦,打印区会提示需要相应的模块文件哒)

这里在 mp_load.js 里已经取到了主路径,可以将之前加载模块处代码修改成:

if (a.length > 0) {for (let i = 0; i < a.length; i++) {// let mf='./static/modules/'+a[i]+'.js'let mf = bmapcfg.home + 'modules/' + a[i] + '.js';debugger oa(mf);console.log('加载模块文件:' + mf) //IE error}} else {f.DK()}

到这里,离线地图就开发完成啦!

四、回答评论中常见的问题-08-04 更新

1、Error in nextTick: “ReferenceError: BMap is not defined”

需要进行vue.config.js配置,详细见我另一篇文章:在线地图

2、地图瓦片对应不上,修改的getTilesUrl这个地方的a里面的x,y都是代表的什么

附上图给大家参考下,具体暂时没研究

3、Uncaught SyntaxError: Unexpected token ‘<’,

这里列一下小伙伴们出现并且已经解决的情况:

1、ak是你自己去百度官网申请的

2、申请ak时选择的是浏览器端

3、js等等的路径不正确也会有这个错

4、实在不行,参考问题5,还不行的话可能又是个新问题,可以一起讨论看看

4、下载的依赖模块js点开提示 We’re sorry but section doesn’t work properly without JavaScript enabled. Please enable it to continue.

这句话的意思是浏览器不支持javascript,但是不可能的,这不科学,所以一般都是js文件报错了,比如你想要获取js文件,但是响应头content-type却是html

解决方法参考:

这里需要看下加载的js文件资源名称是否为.js后缀,如果不是,找到加载该js路径的地方进行修改,详细步骤参考问题5

5、Uncaught SyntaxError: Unexpected token ‘<’ map_e1g5hy.js&v=3.0&seckey=undefined:1 ;

首先感谢这几位小伙伴,详细的报错引起了我的关注,因为我之前并没有出现这个问题,评论里有部分小伙伴在我提醒常见问题3中的解决方法后成功运行,我就一直以为是文件路径之类的问题,也没自己去试,近几天特别多小伙伴跟我提到这个问题,于是自己重新试了下,果然……就离谱啊,于是开始排查原因,这里省略一万只羊驼……

解决方法参考:

1、首先是这样的现象,报了一堆错,地图就展示了一张图,不能拖动也不能缩放,标记点也不出现(前提是这里的功能你都设置了),模块已经下载了,却还是打印,怎么刷新也不管用,如下

2、咱们点击map_e1g5hy.js&v=3.0&seckey=undefined:1会跳转到资源管理,现在我们会发现,明明是加载js,却显示index.html报错了,离谱

3、我们点击network,选择js,会发现content-type为html;点击preview,会出现问题4中描述的现象

4、我们点点其他js文件,发现js就要有js的样子嘛,map_e1g5hy.js&v=3.0&seckey=undefined:1你这整了一堆什么玩意儿,后缀还不是.js

5、这个其实就是我们加载模块时,模块资源加载路径出错了,我只要加载map_e1g5hy.js却给我整了map_e1g5hy.js&v=3.0&seckey=undefined:1,于是回到baidu-api.js,用&mod=查找(步骤3.1),看到加载模块oa(mf),在下面最新的截图中是qa(mf),这里mf就是模块路径,一看写的对的呀,其实这不是我们的问题,嘎嘎,baidu-api.js会不定时更新,每个人都不一样,隔段时间也会不一样,大家看步骤吼(这里附上的图是最近会出问题的版本,跟上面步骤中的图参数会不一样,知道是这个函数就好),ctrl+点击qa,定位到qa(mf)函数,我们发现就是步骤3.2中限制调用外部资源的地方,然后我们发现官方给模块地址加上了"&v=3.0&seckey=" + pa这个玩意儿,其中pa是window.BMAP_SECKEY,最要命的是,这里的key还undefined!!!,对比之前的oa(mf)函数,我们发现的确是最新版本才出现的赋值,于是我们把它注释掉,再去刷新一下页面就ok啦!具体官方为什么会更新这一步,原因不详,后面知道了我再更新吧。

最后,这篇关于离线地图的步骤记录呢大部分都是参照vue集合离线百度地图这个作者的,再写一遍主要就是加深印象,也为了自己以后查阅方便,如有小伙伴不清楚怎么下载和使用太乐地图下载器,可以点这个链接查看哦

对于出现的问题,大家可以参考下,如有不当,欢迎指出,评论中出现新的问题,解决过后将及时更新

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。