地图展示
由于ol没有DB09的坐标系,当需要使用openlayers加载百度地图的瓦片资源时,地图的projection最好是DB09,如果使用EPSG:3857
也是可以加载出底图的,但会出现点位偏移,位置不准确等问题,点位也会随着zoom变化而移动。
以下是通过DB:09
的方式加载百度底图,然后再将需要展示的点位数据转为百度墨卡即可。
创建百度地图的source
/*
* @Description:BaiDuSource.js
* @Author: zm
* @Date: 2024-07-16 14:06:26
* @LastEditTime: 2024-09-11 15:32:37
* @LastEditors: zm 1540588534@qq.com
*/
import { TileImage } from "ol/source";
import TileGrid from "ol/tilegrid/TileGrid";
export default class BaiDuDiTu extends TileImage {
constructor(opt) {
const options = opt || {};
const tileGrid =
options.tileGrid ||
BaiDuDiTu.getTileGrid(options.projection || "EPSG:3857");
const superOptions = {
projection: options.projection || "EPSG:3857",
tileGrid,
tileUrlFunction: function (tileCoord) {
if (!tileCoord) return "";
let z = tileCoord[0];
let x = tileCoord[1];
let y = -tileCoord[2] - 1; //ol6版本有偏移问题
// 对编号xy处理
let baiduX = x < 0 ? "M" + -x : x;
let baiduY = y < 0 ? "M" + -y : y;
return (
"/onlinelabel/?qt=tile&x=" +
baiduX +
"&y=" +
baiduY +
"&z=" +
z +
"&styles=pl&udt=20151021&scaler=1&p=1"
);
},
};
super(superOptions);
}
/**
* @function BaiDuDiTu.getTileGrid
* @description 获取瓦片网格
* @param {Object} projection - 投影参考对象
* @returns {ol.tilegrid.WMTS} 返回瓦片网格对象
*/
static getTileGrid(projection) {
if (projection === "EPSG:4326" || projection === "EPSG:4490") {
return BaiDuDiTu.default4326TileGrid();
}
if (projection === "BD:09") {
return BaiDuDiTu.defaultBD09TileGrid();
}
return BaiDuDiTu.default3857TileGrid();
}
/**
* @function BaiDuDiTu.default4326TileGrid
* @description 获取默认 4326 网格瓦片
* @returns {ol.tilegrid.WMTS} 返回默认 4326 网格瓦片对象
*/
static default4326TileGrid() {
const tdtWgs84Resolutions = [];
const matrixIds = [];
for (let i = 1; i < 19; i += 1) {
tdtWgs84Resolutions.push((0.703125 * 2) / 2 ** i);
matrixIds.push(i);
}
const tileGird = new TileGrid({
extent: [-180, -90, 180, 90],
resolutions: tdtWgs84Resolutions,
origin: [-180, 90],
matrixIds,
minZoom: 1,
});
return tileGird;
}
/**
* @function Tianditu.default3857TileGrid
* @description 获取默认 3857 网格瓦片
* @returns {ol.tilegrid.WMTS} 返回默认 3857 网格瓦片对象
*/
static default3857TileGrid() {
const resolutions = [];
const matrixIds = [];
for (let i = 1; i < 19; i += 1) {
resolutions[i] = Math.pow(2, 18 - i);
matrixIds.push(i);
}
const tileGird = new TileGrid({
resolutions,
matrixIds,
origin: [0, 0],
minZoom: 1,
});
return tileGird;
}
/**
* @function BaiDuDiTu.defaultBD09TileGrid
* @description
* @returns {ol.tilegrid.WMTS}
*/
static defaultBD09TileGrid() {
const resolutions = [];
for (let i = 1; i < 19; i += 1) {
resolutions[i] = Math.pow(2, 18 - i);
}
const tileGird = new TileGrid({
resolutions,
origin: [0, 0],
minZoom: 1,
});
return tileGird;
}
}
创建地图map
/*
* @Description:BaiDuMap.js
* @Author: zm
* @Date: 2024-07-15 09:59:35
* @LastEditTime: 2024-09-11 18:43:05
* @LastEditors: zm 1540588534@qq.com
*/
import "ol/ol.css";
import Map from "ol/Map.js";
import View from "ol/View.js";
import TileLayer from "ol/layer/Tile.js";
import BaiDuDiTu from "@/common/map/baidu/BaiDuSource.js";
import { PROJECTION_DB09, getProjBD09 } from "@/common/map/projects.js";
import { BASEMAP_IMAGE_LAYER } from "@/common/map/layer-ids.js";
import { lngLatToMercator } from "./BD09.js";
const baiduMap = new Map({
controls: [],
layers: [
new TileLayer({
id: BASEMAP_IMAGE_LAYER,
source: new BaiDuDiTu({ projection: PROJECTION_DB09 }),
visible: true,
}),
],
view: new View({
projection: getProjBD09(PROJECTION_DB09),
center: lngLatToMercator([120.098926, 29.343227]),
maxZoom: 20,
minZoom: 5,
zoom: 8,
}),
});
export default baiduMap;
在vue组件中使用
TheHomeGis.vue<div :class="$style['map']" id="BaiDuMap"></div>
绑定容器即可
import baiduMap from "@/common/map/baidu/BaiDuMap.js";
mounted() {
this.baiduMap.setTarget("BaiDuMap");
},
beforeDestroy() {
this.baiduMap.setTarget("");
}
引用的其他文件
/*
* @Description:@/common/map/projects.js
* @Author: zm
* @Date: 2024-09-05 16:35:23
* @LastEditTime: 2024-09-12 19:34:15
* @LastEditors: zm 1540588534@qq.com
*/
import { get as ProjGet, addProjection, Projection } from "ol/proj";
export const PROJECTION_4326 = "EPSG:4326";
export const PROJECTION_3857 = "EPSG:3857";
export const PROJECTION_DB09 = "BD:09";
export const getProjBD09 = (projCode) => {
let projection = ProjGet(projCode);
if (projection) {
return projection;
}
let projBD09 = new Projection({
code: "BD:09",
extent: [-20037726.37, -11708041.66, 20037726.37, 12474104.17],
units: "m",
axisOrientation: "neu",
global: false,
});
addProjection(projBD09);
return projection;
};
export const BASEMAP_IMAGE_LAYER = 'BASEMAP_IMAGE_LAYER';
BD09.js
/* eslint-disable no-redeclare */
/* eslint-disable no-undef */
/* eslint-disable no-useless-escape */
var MCBAND = [12890594.86, 8362377.87, 5591021, 3481989.83, 1678043.12, 0];
var LLBAND = [75, 60, 45, 30, 15, 0];
var MC2LL = [
[
1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331,
200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339,
2.57121317296198, -0.03801003308653, 17337981.2,
],
[
-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289,
96.32687599759846, -1.85204757529826, -59.36935905485877, 47.40033549296737,
-16.50741931063887, 2.28786674699375, 10260144.86,
],
[
-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616,
59.74293618442277, 7.357984074871, -25.38371002664745, 13.45380521110908,
-3.29883767235584, 0.32710905363475, 6856817.37,
],
[
-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591,
40.31678527705744, 0.65659298677277, -4.44255534477492, 0.85341911805263,
0.12923347998204, -0.04625736007561, 4482777.06,
],
[
3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062,
23.10934304144901, -0.00023663490511, -0.6321817810242, -0.00663494467273,
0.03430082397953, -0.00466043876332, 2555164.4,
],
[
2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8,
7.47137025468032, -0.00000353937994, -0.02145144861037, -0.00001234426596,
0.00010322952773, -0.00000323890364, 826088.5,
],
];
var LL2MC = [
[
-0.0015702102444, 111320.7020616939, 1704480524535203, -10338987376042340,
26112667856603880, -35149669176653700, 26595700718403920,
-10725012454188240, 1800819912950474, 82.5,
],
[
0.0008277824516172526, 111320.7020463578, 647795574.6671607,
-4082003173.641316, 10774905663.51142, -15171875531.51559,
12053065338.62167, -5124939663.577472, 913311935.9512032, 67.5,
],
[
0.00337398766765, 111320.7020202162, 4481351.045890365, -23393751.19931662,
79682215.47186455, -115964993.2797253, 97236711.15602145,
-43661946.33752821, 8477230.501135234, 52.5,
],
[
0.00220636496208, 111320.7020209128, 51751.86112841131, 3796837.749470245,
992013.7397791013, -1221952.21711287, 1340652.697009075, -620943.6990984312,
144416.9293806241, 37.5,
],
[
-0.0003441963504368392, 111320.7020576856, 278.2353980772752,
2485758.690035394, 6070.750963243378, 54821.18345352118, 9540.606633304236,
-2710.55326746645, 1405.483844121726, 22.5,
],
[
-0.0003218135878613132, 111320.7020701615, 0.00369383431289,
823725.6402795718, 0.46104986909093, 2351.343141331292, 1.58060784298199,
8.77738589078284, 0.37238884252424, 7.45,
],
];
// eslint-disable-next-line no-unused-vars
// 百度经纬度转百度墨卡托
export function lngLatToMercator(T) {
var c = new cd(T[0], T[1]);
var r = convertLL2MC(c);
return [r.lng, r.lat];
}
// eslint-disable-next-line no-unused-vars
export function mercatorToLngLat(T) {
var c = new cd(T[0], T[1]);
var r = convertMC2LL(c);
return [r.lng, r.lat];
}
export function convertLL2MC(T) {
var cL, cN;
T.lng = getLoop(T.lng, -180, 180);
T.lat = getRange(T.lat, -74, 74);
cL = new cd(T.lng, T.lat);
for (var cM = 0; cM < LLBAND.length; cM++) {
if (cL.lat >= LLBAND[cM]) {
cN = LL2MC[cM];
break;
}
}
if (!cN) {
for (var cM = LLBAND.length - 1; cM >= 0; cM--) {
if (cL.lat <= -LLBAND[cM]) {
cN = LL2MC[cM];
break;
}
}
}
var cO = convertor(T, cN);
var T = new cd(cO.lng.toFixed(2), cO.lat.toFixed(2));
return T;
}
export function convertMC2LL(cL) {
var cM, cO;
cM = new cd(Math.abs(cL.lng), Math.abs(cL.lat));
for (var cN = 0; cN < MCBAND.length; cN++) {
if (cM.lat >= MCBAND[cN]) {
cO = MC2LL[cN];
break;
}
}
var T = convertor(cL, cO);
var cL = new cd(T.lng.toFixed(6), T.lat.toFixed(6));
return cL;
}
function getRange(cM, cL, T) {
if (cL != null) {
cM = Math.max(cM, cL);
}
if (T != null) {
cM = Math.min(cM, T);
}
return cM;
}
function getLoop(cM, cL, T) {
while (cM > T) {
cM -= T - cL;
}
while (cM < cL) {
cM += T - cL;
}
return cM;
}
function convertor(cM, cN) {
if (!cM || !cN) {
return;
}
var T = cN[0] + cN[1] * Math.abs(cM.lng);
var cL = Math.abs(cM.lat) / cN[9];
var cO =
cN[2] +
cN[3] * cL +
cN[4] * cL * cL +
cN[5] * cL * cL * cL +
cN[6] * cL * cL * cL * cL +
cN[7] * cL * cL * cL * cL * cL +
cN[8] * cL * cL * cL * cL * cL * cL;
T *= cM.lng < 0 ? -1 : 1;
cO *= cM.lat < 0 ? -1 : 1;
return new cd(T, cO);
}
function cd(T, cL) {
if (isNaN(T)) {
T = bV(T);
T = isNaN(T) ? 0 : T;
}
if (b3(T)) {
T = parseFloat(T);
}
if (isNaN(cL)) {
cL = bV(cL);
cL = isNaN(cL) ? 0 : cL;
}
if (b3(cL)) {
cL = parseFloat(cL);
}
this.lng = T;
this.lat = cL;
}
cd.isInRange = function (T) {
return T && T.lng <= 180 && T.lng >= -180 && T.lat <= 74 && T.lat >= -74;
};
cd.prototype.equals = function (T) {
return T && lat == T.lat && lng == T.lng;
};
function bV(cN) {
var cL = "";
var cU,
cS,
cQ = "";
var cT,
cR,
cP,
cO = "";
var cM = 0;
var T = /[^A-Za-z0-9\+\/\=]/g;
if (!cN || T.exec(cN)) {
return cN;
}
cN = cN.replace(/[^A-Za-z0-9\+\/\=]/g, "");
do {
cT = cf.indexOf(cN.charAt(cM++));
cR = cf.indexOf(cN.charAt(cM++));
cP = cf.indexOf(cN.charAt(cM++));
cO = cf.indexOf(cN.charAt(cM++));
cU = (cT << 2) | (cR >> 4);
cS = ((cR & 15) << 4) | (cP >> 2);
cQ = ((cP & 3) << 6) | cO;
cL = cL + String.fromCharCode(cU);
if (cP != 64) {
cL = cL + String.fromCharCode(cS);
}
if (cO != 64) {
cL = cL + String.fromCharCode(cQ);
}
cU = cS = cQ = "";
cT = cR = cP = cO = "";
} while (cM < cN.length);
return cL;
}
function b3(T) {
return typeof T == "string";
}