map-preview
使用高德地图、百度地图切片和openlayers
实现广西街道地图离线使用。
切片下载和部署
请使用此工具进行切片下载:mapTileDownload
下载的切片通常会很庞大,第 17、18、19 层级的文件数据量大、文件多,直接上传至服务器会非常缓慢,请使用压缩工具进行压缩 压缩也要根据电脑配置分多文件压缩,否则压缩到最后内存溢出失败了就白白压缩那么久了!通常 1-17 一个压缩包、18 分为一个或两个包,一个包大小为 4g-6g 左右大小
使用
sftp
上传文件到服务器:bashscp -r '/F:/地图切片/百度广西区域街道图/roadmap-1-17.7z' root@192.168.1.207:/data/daye01/map/
登录服务器,安装压缩工具
7za
:bashyum install -y p7zip
解压缩上传的文件夹到指定目录:
bash7za x 'roadmap-1-17.7z' -r -o./bmap
配置跨域资源访问,以
nginx
为例:若资源和客户端代码在同一服务上可忽略此操作
为资源静态访问添加
nginx
配置:nginxlocation ^~ /map { # 处理以/map开头的请求 add_header 'Access-Control-Allow-Headers' '*' always; add_header 'Access-Control-Allow-Origin' '*' always; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE' always; add_header 'Access-Control-Allow-Headers' '*' always; add_header 'Access-Control-Max-Age' 1728000 always; add_header 'Content-Length' 0; add_header 'Content-Type' 'text/plain; charset=utf-8'; return 204; } root /data; expires 3d; }
之后就可以通过
/map/bmap/{z}/{x}/{y}.png
来访问切片了
demo
-百度
js
/*定义百度地图分辨率与瓦片网格*/
const resolutions = [];
for (var i = 0; i <= 19; i++) {
resolutions[i] = Math.pow(2, 18 - i);
}
// 创建百度地理坐标系,
const projBD09 = new ol.proj.Projection({
// 坐标系代码
code: 'BD:09',
// 坐标系范围
extent: [-180, -90, 180, 90],
// 坐标系分辨率使用的单位
units: 'degrees',
// 用于确定坐标系的坐标轴方向
axisOrientation: 'enu',
});
// 添加到openlayers支持的坐标系
ol.proj.addProjection(projBD09);
// 创建百度投影坐标系
const projBD09Meter = new ol.proj.Projection({
// 坐标系代码
code: 'BD:09-Meter',
// 坐标系范围
extent: [-20037726.37, -11708041.66, 20037726.37, 12474104.17],
// 坐标系分辨率使用的单位
units: 'm',
// 用于确定坐标系的坐标轴方向
axisOrientation: 'neu',
});
// 添加到openlayers支持的坐标系
ol.proj.addProjection(projBD09Meter);
// 定义百度投影坐标系和 BD:09 坐标系之间的转换规则
ol.proj.addCoordinateTransforms(
'BD:09',
'BD:09-Meter',
function (coordinate) {
return gcoord.transform(
coordinate, // 经纬度坐标
gcoord.BD09, // 当前坐标系
gcoord.BD09Meter // 目标坐标系
);
},
function (coordinate) {
return gcoord.transform(
coordinate, // 投影坐标
gcoord.BD09Meter, // 当前坐标系
gcoord.BD09 // 目标坐标系
);
}
);
/*加载百度地图离线瓦片不能用ol.source.XYZ,ol.source.XYZ针对谷歌地图(注意:是谷歌地图)而设计,而百度地图与谷歌地图使用了不同的投影、分辨率和瓦片网格。因此这里使用ol.source.TileImage来自行指定投影、分辨率、瓦片网格。*/
const tileGrid = new ol.tilegrid.TileGrid({
origin: [0, 0],
resolutions: resolutions,
});
// 创建百度坐标系切片资源
const bMapSources = new ol.source.TileImage({
projection: 'BD:09-Meter',
tileGrid: tileGrid,
tileUrlFunction: function (tileCoord, pixelRatio, proj) {
let z = tileCoord[0];
let x = tileCoord[1];
let y = -tileCoord[2] - 1;
if (x < 0) x = 'M' + -x;
if (y < 0) y = 'M' + -y;
// return `http://111.12.91.15:28802/map/bmap/${z}/${x}/${y}.png`;
return `https://maponline3.bdimg.com/tile/?qt=vtile&z=${z}&x=${x}&y=${y}&styles=pl&scaler=1&udt=20230616&from=jsapi3_0`;
},
});
// 创建切片图层
const bdMapLayers = new ol.layer.Tile({
source: bMapSources,
});
export default () => {
const view = new ol.View({
// 在百度地图jsapi中为了方便开发者,在底层将经纬度自动转换为墨卡托投影坐标,所以可以直接使用经纬度进行定位
// 在使用openlayers的时候,需要手动对经纬度坐标进行转换,转换为百度的墨卡托投影坐标才能正确显示
center: ol.proj.transform(
[108.34171638707808, 22.818581259540537],
'BD:09',
'BD:09-Meter'
),
zoom: 10, // 缩放
maxZoom: 19,
projection: 'BD:09-Meter',
// 使用和百度切片资源设置的分辨率
resolutions: bMapSources.getTileGrid().getResolutions(),
// 设置缩放级别为整数
constrainResolution: true,
// 关闭无极缩放地图
smoothResolutionConstraint: false,
});
return new ol.Map({
target: 'map',
layers: [bdMapLayers],
view: view,
controls: ol.control.defaults.defaults({
zoom: true,
rotate: true,
attribution: true,
}),
});
};
demo
-高德
js
// 百度坐标
const bdPoint = [108.34171638707808, 22.818581259540537];
// 转换为 GCJ02 坐标
export const GCJ02Point = gcoord.transform(
bdPoint, // 经纬度坐标
gcoord.BD09, // 当前坐标系
gcoord.GCJ02 // 目标坐标系
);
// 创建 GCJ02 地理坐标系,
const GCJ02 = new ol.proj.Projection({
// 坐标系代码
code: 'GCJ:02',
// 坐标系范围
extent: [-180, -90, 180, 90],
// 坐标系分辨率使用的单位
units: 'degrees',
// 用于确定坐标系的坐标轴方向
axisOrientation: 'enu',
});
// 添加到openlayers支持的坐标系
ol.proj.addProjection(GCJ02);
// 定义GCJ02地理坐标系和web墨卡托投影坐标系之间的转换规则
ol.proj.addCoordinateTransforms(
'GCJ:02',
'EPSG:3857',
function (coordinate) {
// GCJ02火星坐标系转换为投影坐标系是使用经纬度直接转换,只有当前地理坐标系为WGS84时,经纬度可以被直接转换为EPSG:3857。
// 若当前坐标系使用 GCJ02,算法会将GCJ02先转为WGS84,再转为EPSG:3857,所以这里将GCJ02视为WGS84进行直接转换
return gcoord.transform(
coordinate, // 经纬度坐标
gcoord.WGS84, // 当前坐标系
gcoord.EPSG3857 // 目标坐标系
);
},
function (coordinate) {
return gcoord.transform(
coordinate, // 投影坐标
gcoord.EPSG3857, // 当前坐标系
gcoord.WGS84 // 目标坐标系
);
}
);
export default () => {
const onlineUrl =
'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}';
const offlineUrl = 'http://111.12.91.15:28802/map/amap' + '/{z}/{x}/{y}.png'; // 设置本地离线瓦片所在路径
return new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.XYZ({
url: onlineUrl,
}),
}),
],
view: new ol.View({
center: ol.proj.transform(GCJ02Point, 'GCJ:02', 'EPSG:3857'),
zoom: 10, // 缩放
}),
controls: ol.control.defaults.defaults({
zoom: true,
rotate: true,
attribution: true,
}),
});
};