openlayers 6 加载百度地图瓦片(在线,离线)
前言
众所周知,
EPSG:4326
表示大地经纬度坐标,也叫WGS84
坐标EPSG:3857
则表示大地平面坐标,也叫墨卡托坐标,openlayers
本身支持这两个坐标互相转换而据我所知,国内使用的坐标都是做了偏移的,一般是西安80(EPSG:4610)、北京54(EPSG:2433)。
高德使用的是
GCJ-02
坐标,而百度则是再GCJ-02
基础上做了偏移为BD:09
坐标,一般知道坐标的编码使用openlayers
就能互相转换,但是GCJ-02
、BD:09
都是通过算法加密了,需要我们手动使用算法完成转换我在此基础上封装了一个库@tomiaa/coordinate-transform
百度经纬度坐标
BD:09
:你可以在百度坐标拾取上取得的坐标是百度经纬度坐标
示例
点击查看代码
vue
<template>
<div
ref="map"
class="map-example"
></div>
<div
ref="position"
class="position"
></div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from "vue"
import "ol/ol.css"
import { Map, View, Feature } from "ol"
import TileLayer from "ol/layer/Tile"
import layerVector from "ol/layer/Vector"
import { defaults, MousePosition } from "ol/control"
import { TileImage, Vector } from "ol/source"
import TileGrid from "ol/tilegrid/TileGrid"
import { Style, Fill, Stroke, Circle } from "ol/style"
import { Point } from "ol/geom"
import { createStringXY } from "ol/coordinate"
import '@/utils/src/openlayersProjDefs'
const map = ref()
const position = ref()
onMounted(() => {
// const center = transform([112.926305, 28.204233], "EPSG:4326", "baidu") // 坐标
// const center = [112.926305, 28.204233] // 4326
const center = [112.93816837836393, 28.206985612845706] // bd:09
const olMap = new Map({
target: map.value,
layers: [
new TileLayer({
source: new TileImage({
projection: "baidu",
// tilePixelRatio: 2,
tileGrid: new TileGrid({
origin: [0, 0],
resolutions: Array.from({ length: 19 }).map((_, i) =>
Math.pow(2, 18 - i)
),
}),
tileUrlFunction(tileCoord) {
if (!tileCoord) return ""
let z: string | number = tileCoord[0]
let x: string | number = tileCoord[1]
let y: string | number = -tileCoord[2] - 1
if (x < 0) x = "M" + -x
if (y < 0) y = "M" + -y
/* 本地离线地图 */
// return `/baidu_tiles/${z}/${x}/${y}.png`
/* 在线地图 */
// return (
// "http://online3.map.bdimg.com/onlinelabel/?qt=tile&x=" +
// x +
// "&y=" +
// y +
// "&z=" +
// z +
// "&styles=pl&udt=20151021&scaler=1&p=1"
// )
return `https://maponline2.bdimg.com/tile/?qt=vtile&x=${x}&y=${y}&z=${z}&styles=pl&scaler=1&udt=20240805&from=jsapi2_0`
},
}),
}),
],
view: new View({
// projection: "EPSG:4326",
projection: "BD:09",
center,
zoom: 8,
// constrainResolution: true,
}),
controls: defaults({
attributionOptions: {
collapsible: true, // 右下角详细信息默认收缩
},
}).extend([
new MousePosition({
coordinateFormat: createStringXY(6), // 保留 3 位小数
projection: "BD:09", // 输出投影的坐标,默认3857
target: position.value,
}),
]),
})
//创建一个点
const point = new Feature({
geometry: new Point(center),
})
//设置点1的样式信息
point.setStyle(
new Style({
//填充色
fill: new Fill({
color: "rgba(255, 255, 255, 0.2)",
}),
//边线颜色
stroke: new Stroke({
color: "#ffcc33",
width: 2,
}),
//形状
image: new Circle({
radius: 17,
fill: new Fill({
color: "#ffcc33",
}),
}),
})
)
//实例化一个矢量图层Vector作为绘制层
const source = new Vector({
features: [point],
})
//创建一个图层
const vector = new layerVector({
source: source,
})
//将绘制层添加到地图容器中
olMap.addLayer(vector)
})
</script>
<style lang="scss" scoped>
.map-example {
width: 100%;
height: 80vh;
}
.position {
position: absolute;
top: -50px;
right: 0;
white-space: nowrap;
}
</style>
坐标转换实现
点击查看代码
ts
import { addCoordinateTransforms, addProjection, Projection } from "ol/proj"
import proj4 from "proj4"
import { register } from "ol/proj/proj4"
import {
BD092BaiduMercator,
BD092Mercator,
BD092WSG84,
CGCS20002BaiduMercator,
WSG842BD09,
WSG842BaiduMercator,
baiduMercator2BD09,
baiduMercator2CGC2000,
baiduMercator2Mercator,
baiduMercator2WSG84,
mercator2BD09,
mercator2BaiduMercator,
} from "@tomiaa/coordinate-transform"
/* -------- 坐标定义 --------- */
/* 天地图 CGC2000 */
proj4.defs("EPSG:4490", "+proj=longlat +ellps=GRS80 +no_defs +type=crs")
register(proj4)
/* 百度墨卡托坐标 */
const baiduMercator = new Projection({
code: "baidu",
extent: [
-20022743.74356534, -12474104.1741364, 20022743.74356534, 12474104.1741364,
],
// extent: [-20037726.37, -12474104.17, 20037726.37, 12474104.17],
units: "m",
})
/* 百度 BD:09 经纬度坐标 */
const BD09 = new Projection({
code: "BD:09",
units: "m",
extent: [-179.86541124, -74, 179.86541124, 74],
})
addProjection(BD09)
addProjection(baiduMercator)
/* 百度墨卡托 <==> WSG84 */
addCoordinateTransforms(
"EPSG:4326",
baiduMercator,
WSG842BaiduMercator,
baiduMercator2WSG84
)
/* 百度墨卡托 <==> 墨卡托 */
addCoordinateTransforms(
"EPSG:3857",
baiduMercator,
mercator2BaiduMercator,
baiduMercator2Mercator
)
/* WSG84 <==> BD09 */
addCoordinateTransforms("EPSG:4326", BD09, WSG842BD09, BD092WSG84)
/* 墨卡托 <==> BD09 */
addCoordinateTransforms("EPSG:3857", BD09, mercator2BD09, BD092Mercator)
/* 百度墨卡托 <==> BD:09 */
addCoordinateTransforms(
BD09,
baiduMercator,
BD092BaiduMercator,
baiduMercator2BD09
)
/* 百度墨卡托 <==> EPSG:4490(天地图) */
addCoordinateTransforms(
baiduMercator,
"EPSG:4490",
baiduMercator2CGC2000,
CGCS20002BaiduMercator
)