Web端百度地图离线部署与WGS84坐标转换实战
在作业点无网络覆盖的场景下,实现Web版百度地图的离线开发主要涉及三个核心环节:获取并改造离线API、下载本地瓦片图数据,以及处理GPS接收机传来的WGS84坐标与百度坐标系(BD-09)之间的偏差。本文将基于百度地图API V2.0版本,详细介绍如何通过配置JS参数实现无网加载,并提供精确的Java版坐标转换算法代码,帮助开发者快速搭建离线地图系统。
实现离线地图的核心准备条件
由于百度地图官方并不直接支持完全离线的服务端运行,我们需要通过技术手段将在线的代码逻辑重构为本地可执行的模式。具体需要解决以下三个技术痛点:
- 离线API的获取与封装: 替换在线引用的JS库为本地文件。
- 离线瓦片图的获取: 提前缓存所需区域的地图切片。
- 坐标系的转换: GPS设备通常返回WGS84坐标,而百度地图使用BD-09坐标,且两者转换涉及保密算法,需通过本地代码实现。
第一步:配置并加载离线百度地图API
首先,你需要准备一份经过处理的离线API包(基于V2.0版本)。在项目的根目录下,需要引入核心的加载文件和样式表。
1. 引入资源文件
在HTML中仅需加载本地的离线JS文件和CSS文件:
<script type="text/javascript" src="baidumapv2/baidumap_offline_v2_load.js"></script>
<link rel="stylesheet" type="text/css" href="../../baidumapv2/css/baidu_map_v2.css"/>
2. 修改配置文件
打开 baidumap_offline_v2_load.js,定位到 bdmapcfg 对象,根据你下载的瓦片图片格式进行修改:
var bdmapcfg = {
'imgext': '.jpg', // 瓦片图的后缀,通常为 .png 或 .jpg
'tiles_dir': '' // 瓦片图的目录,默认为 baidumap_v2/tiles/ 目录
};
3. 初始化地图实例
创建一个用于显示地图的容器,并通过CSS控制其宽高。随后编写JS代码进行初始化。注意:离线模式下不支持“设置当前城市”功能,部分控件(如地图类型切换中的卫星/三维视图)可能不可用。
<script type="text/javascript">
// 创建Map实例
var map = new BMap.Map("map_demo");
// 初始化地图,设置中心点坐标(北京)和级别
map.centerAndZoom(new BMap.Point(116.404, 39.915), 8);
// 开启鼠标滚轮缩放
map.enableScrollWheelZoom(true);
// 添加导航缩放控件
map.addControl(new BMap.NavigationControl());
</script>
第二步:获取并放置本地瓦片图
为了在离线状态下显示地图内容,必须提前下载对应区域的瓦片图。可以使用专业的电子地图下载器(如全能电子地图下载器)或其他抓取工具,按层级、经度、纬度范围下载所需的切片图片。
下载完成后,将图片按照配置的目录结构存放。例如,如果配置中 tiles_dir 为空,则默认路径应为 baidumap_v2/tiles/ 文件夹内。确保图片后缀与JS配置中的 imgext 一致。
第三步:实现WGS84到百度坐标的本地转换
车载接收机反馈的通常是WGS84坐标,直接将其放入百度地图会产生较大偏差。由于百度对GCJ-02(国测局坐标)进行了二次加密形成BD-09(百度坐标),我们可以利用开源的数学模型在客户端或服务端完成这一转换,无需调用HTTP API。
以下是一个经过验证的Java版坐标转换工具类 CoorConvertUtil,包含WGS转GCJ、GCJ转BD以及度分转度的方法:
public class CoorConvertUtil {
//圆周率
static double pi = 3.14159265358979324;
//卫星椭球坐标投影到平面坐标系的投影因子
static double a = 6378245.0;
//椭球的偏心率
static double ee = 0.00669342162296594323;
//圆周率转换量
public final static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
/**
* WGS坐标转百度坐标 (WGS84 -> GCJ-02 -> BD-09)
*/
public static double[] wgs2bd(double lat, double lon) {
double[] wgs2gcj = wgs2gcj(lat, lon);
double[] gcj2bd = gcj2bd(wgs2gcj[0], wgs2gcj[1]);
return gcj2bd;
}
/**
* GCJ坐标转百度坐标
*/
public static double[] gcj2bd(double lat, double lon) {
double x = lon, y = lat;
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
double bd_lon = z * Math.cos(theta) + 0.0065;
double bd_lat = z * Math.sin(theta) + 0.006;
return new double[] { bd_lat, bd_lon };
}
/**
* 百度坐标转GCJ坐标
*/
public static double[] bd2gcj(double lat, double lon) {
double x = lon - 0.0065, y = lat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
double gg_lon = z * Math.cos(theta);
double gg_lat = z * Math.sin(theta);
return new double[] { gg_lat, gg_lon };
}
/**
* WGS坐标转GCJ坐标
*/
public static double[] wgs2gcj(double lat, double lon) {
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
double[] loc = { mgLat, mgLon };
return loc;
}
private static double transformLat(double lat, double lon) {
double ret = -100.0 + 2.0 * lat + 3.0 * lon + 0.2 * lon * lon + 0.1 * lat * lon + 0.2 * Math.sqrt(Math.abs(lat));
ret += (20.0 * Math.sin(6.0 * lat * pi) + 20.0 * Math.sin(2.0 * lat * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lon * pi) + 40.0 * Math.sin(lon / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(lon / 12.0 * pi) + 320 * Math.sin(lon * pi/ 30.0)) * 2.0 / 3.0;
return ret;
}
private static double transformLon(double lat, double lon) {
double ret = 300.0 + lat + 2.0 * lon + 0.1 * lat * lat + 0.1 * lat * lon + 0.1 * Math.sqrt(Math.abs(lat));
ret += (20.0 * Math.sin(6.0 * lat * pi) + 20.0 * Math.sin(2.0 * lat * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lat * pi) + 40.0 * Math.sin(lat / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(lat / 12.0 * pi) + 300.0 * Math.sin(lat / 30.0 * pi)) * 2.0 / 3.0;
return ret;
}
/**
* 度分转度 (用于处理GPS原始数据格式)
* @param lat 纬度 ddmm.mmmm
* @param lon 经度 dddmm.mmmm
*/
public static double[] dufen2du(String lat, String lon) {
double latD=Double.parseDouble(lat.substring(0, 2));
double latM=Double.parseDouble(lat.substring(2));
double latNew=latD+latM/60;
double lonD=Double.parseDouble(lon.substring(0, 3));
double lonM=Double.parseDouble(lon.substring(3));
double lonNew=lonD+lonM/60;
return new double[] { latNew, lonNew } ;
}
}
在实际业务中,收到GPS数据后,先通过 wgs2bd() 方法转换为百度坐标,再使用 BMap.Point(bd_lon, bd_lat) 添加到地图上,即可在无网环境下精准显示车辆位置。
项目效果展示
完成上述配置和编码后,即可在没有网络连接的情况下,实时画出各车辆的坐标、速度及转向信息。系统能够在局部区域内保持地图的正常加载与交互。
以上就是百度地图JavaScript离线版开发与坐标转换的详细内容,更多关于百度地图开发技巧的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













