百度离线地图,自己动手改造js文件

1,417 阅读5分钟

百度离线地图简单实现

1.0前言

由于第一次接触百度离线地图,踩了很多坑才了解到原来是这么一回事, 现在简单记录下原理, 方便大家自己修改使用!

本质上就是提前下载离线资源, 对线上请求的js文件内容进行处理, 线上请求修改成本地目录路径!

1.png

1. iamges - 存放离线地图访问的一些图片, 例如定位, marker会与一些小图标

2. js/modules - 文件夹存放多个离线模块js内容, 例如marker, infoWindow信息窗口这种, 记住因为随机种子的原因会导致各种请求变量参数改变, 所以都是和min.js的离线请求版本一一对应, (有些百度地图离线设计是就单一个getmodule.js文件, 然后把所有模块写在一起,例如在线百度地图实现就单单一个请求了一个js文件)

2.png 3. js/bm_offline_v2_load.js - index.html只需要引入该load.js文件, 可配置自定义路径, 自动启动min.js文件

4. js/bm_offline_v2_min.js - 百度地图请求的js文件内容

5. tiles - 存放离线瓦片

1.0 介绍下load.js文件

主要是为了方便自己项目自定义配置路径, 不必到js请求文件中代码修改

// 项目根目录index.html
...
    <script>
      // const offLine = window.g && window.g.offline // 这里是我自定义的环境变量, 你可以使用process.env这种
      if (true) { // 演示为true, 项目自己是根据if(offLine){...是否引入百度地图离线
        var script = document.createElement('script')
        script.id = 'mapScript' // 标志方便找到这个脚本路径
        script.src = 'static/js/bm_offline_v2_load.js' //这个文件会自动把修改后的离线js文件引入
        document.head.appendChild(script)
      }
    </script>
 </body>
</html>
// bm_offline_v2_load.js
let bdmapcfg = {
  'imgext': '.png', // 瓦片图的后缀 ------ 根据需要修改,一般是 .png .jpg
  'tiles_dir': '', // 瓦片图的目录,为空默认在 static/tiles/ 目录
  'home': '' // 根目录位置, 例如我的根目录是static, 所有的请求都是从根目录发出的
  // 例如请求load.js 是'static/' + '/js/bm_offline_v2_min.js'
  // 请求模块文件 是'static/' + '/modules/***.js'
  // 请求瓦片图片 是'static/' + '/titles/**/**/***.png'
}

// 上面代码根据自己项目结构修改, 下面保持不动
const fullPath = document.getElementById('mapScript').getAttribute('src') // 提取根目录
console.log('🚀 ~ fullPath:', fullPath, typeof fullPath)
bdmapcfg.home = fullPath.substring(0, fullPath.indexOf('/') + 1) // 取到根目录, +1是为了'/'也包含
// 加载地图API主文件

;(function(){ // 立即执行函数引入min.js文件
  var script = document.createElement('script')
  script.type = 'text/javascript'
  script.src = bdmapcfg.home + 'js/bm_offline_v2_min.js'
  script.async = true
  document.head.appendChild(script)
})()

1.1 找到在线请求文件

  • 首先根据百度地图官网Demo

  • 搜索api?v=2.0找到如下地址

    https://api.map.baidu.com/api?v=2.0&ak=E4805d16520de693a3fe707cdc962045

    复制返回数据中内容中 script 加载的 src 地址,在浏览器中打开;如下

    (function() {
        window.HOST_TYPE = "2";
        window.BMap_loadScriptTime = (new Date).getTime();
        document.write('<script type="text/javascript" src="https://api.map.baidu.com/getscript?v=2.0&ak=E4805d16520de693a3fe707cdc962045&services=&t=20240731110958"></script>');
    }
    )();
    

9.webp

  • 最终得到类似这样的文件内容

4.png 首先可以将复制的百度地图API的代码 在一个网站这里 进行格式化;这样看的比较清楚。

其次注意, 因为百度地图可能为了代码混淆保护其代码? 会出现不同时间请求的js文件会有核心逻辑保持不变, 但有标识符(变量名、函数名等)发生变化, 例如

-   函数名:Xf 变成 ag
-   对象名:fb 变成 gb

尤其在对模块请求上, 例如请求 信息窗口加上随机种子数 infowWindow_aj5h3, 必须要一一匹配才能使用
这方面后续模块后续会提到

所以历史项目的百度地图离线项目都是只能使用已经设定下载好的源码, 现在时间点再去请求离线资源是无法使用的

1.2 修改请求js文件

步骤大致介绍

  • 防止外部http请求, 直接return

  • 把原本的1.一些资源总请求地址 2. 地图模块地址 3.请求瓦片地址

    地址分别改成自己项目目录的地址

例如原本你地图中用到了marker标记模块, js文件会请求'api.map.baidu.com/getmodules?…, marker_l2iycb' ... (<--, 这就是提到marker模块)

现在需要改成 static/moudle/ + marker_l2iycb.js

1. (防止外部http请求, 直接return)

搜索 &callback=BMap._rd._cbk 以及 查看前面是否有代码 * Math.random(), 类似下图

// 加入代码 
 
if (/^http/.test(a)) return; // 屏蔽ak验证,若调用外部资源直接返回

5.png

2. (一些资源总请求地址)

搜索 url.domain.main_domain_nocdn.other, 把下面一行B.la 设置为自己的根目录例如B.la = '/static' 因为正常B.la 可能会指向 api.map.baidu.com/ ...各种请求 现在需要把他引到请求/static 发起

// 加入代码 
B.la = bdmapcfg.home; // 注意根据自己请求文件, 也许你的js这行是 z.ma = ...

6.png

3. (模块地址)

搜索 &mod= 这个是为了找到load函数加载各种模块例如地图的marker, infowWindow信息窗口, 修改地址为本地

```
...
// 0 == a.length ? e.GL() : ra(e.TG.QQ + "&mod=" + a.join(","))  //修改为本地的modules地址加载离线js
// 修改为这种for循环格式, else 对应 ?问好 后面e.GL, for循环执行函数对应 :冒号后面的 ra(其实就只之前外部请求return修改那个函数)
if (a.length > 0) {
    for (i = 0; i < a.length; i++) {
            mf = bdmapcfg.home + "modules/" + a[i] + ".js";
            Qb(mf)
    }
} else {
     e.UK()
}
```

7.png

  1. (请求瓦片地址)

搜索 qt=vtile 且上面有 normal

he.getTilesUrl = function(a, b, c) {
    var d = a.x,
    a = a.y,
    e = Yb("normal"),
    f = 1,
    c = ge[c];
    // this.map.ly() && (f = 2);
    // d = this.map.fb.Hs(d, b).tm;
    // return (fe[Math.abs(d + a) % fe.length] + "?qt=vtile&x=" + (d + "").replace(/-/g....  // 三行全部注释
    // 如果之前没有设置默认为空, 瓦片资源就是 tdir = static/tiles/***
    tdir = bdmapcfg.tiles_dir.length > 0 ? bdmapcfg.tiles_dir: bdmapcfg.home + "tiles";
    return tdir + "/" + b + "/" + d + "/" + a + bdmapcfg.imgext 
    // 其实就是自己项目的瓦片本地地址, 一般瓦片后缀为png
    }

8.png

尾言

这样大致离线百度地图的js文件就改造完成了, 以后新的也可以自己根据进行改造而不用使用历史的离线文件js了

这是我参考的github中的项目, 其中的images文件和modules可以下载参考