OpenLayers 6 如何優(yōu)雅的使用天地圖WMTS服務“經(jīng)緯度投影(CGCS2000)”和“球面墨卡托投影(EPSG:3857)”
最近google.com衛(wèi)星圖和bing衛(wèi)星圖相繼有重大變動,常規(guī)方式已經(jīng)沒辦法使用XYZ方式加載在線圖了,于是我把目光轉向了天地圖。之前以為天地圖是GCJ02加偏的資源,直到看到官網(wǎng)上這么一句話:
于是眼前一亮,申請了一個開發(fā)者API(過程很簡單,略),搞起。
但是因為天地圖在WMTS的基礎上加了個key,沒辦法用getCapablities的方法加載,每次都需要自己配置長長一大堆參數(shù),很煩,干脆封裝了一個 函數(shù),可以通過<地圖類型>+<“投影”類型>的參數(shù)配置方式直接獲得一個ol/layer/Tile類的圖層,在OpenLayers 6.1.1版本下測試通過。個人感覺還挺好用的。
以下是源碼:
/**
* @fileOverview 天地圖WMTS服務API
* @author <a href=”https://blog.csdn.net/nudtcadet”>老胡</a>
* @version 1.0
*/
import { getWidth, getTopLeft } from 'ol/extent';
import WMTS from 'ol/tilegrid/WMTS';
import { WMTS as WMTSSource } from 'ol/source';
import TileLayer from 'ol/layer/Tile';
import { get as getProjection, getTransform } from 'ol/proj';
import { applyTransform } from 'ol/extent';
/**
* @description 獲得一個OpenLayers框架下的ol/layer/Tile類型天地圖圖層
* @param {options} Object 初始化參數(shù)
* @param {options.type} String 與官方名稱相同的圖層類型
* @param {options.proj} String 與官方名稱相同的投影類型
* @param {options.key} String 開發(fā)者秘鑰
*/
export function getTianditu(options) {
let layers = {
'全球境界': 'ibo',
'地形注記': 'cta',
'地形暈渲': 'ter',
'影像注記': 'cia',
'影像底圖': 'img',
'矢量注記': 'cva',
'矢量底圖': 'vec'
}
let projs = {
'經(jīng)緯度投影': 'EPSG:4490',
'球面墨卡托投影': 'EPSG:900913'
}
let matrixSets = {
'經(jīng)緯度投影': 'c',
'球面墨卡托投影': 'w'
}
let projection = getProjection(projs[options.proj]);
let projectionExtent = projection.getExtent();
let origin = projectionExtent ? getTopLeft(projectionExtent) : [-180, 90];
let fromLonLat = getTransform('EPSG:4326', projection);
let width = projectionExtent ? getWidth(projectionExtent) : getWidth(applyTransform([-180.0, -90.0, 180.0, 90.0], fromLonLat));
let resolutions = [];
let matrixIds = [];
for (let z = 1; z < 19; z++) {
resolutions[z] = width / (256 * Math.pow(2, z));
matrixIds[z] = z;
};
let wmtsTileGrid = new WMTS({
origin: origin,
resolutions: resolutions,
matrixIds: matrixIds
});
let wmtsSource = new WMTSSource({
url: "http://t0.tianditu.gov.cn/" + layers[options.type] + "_" + matrixSets[options.proj] + "/wmts?tk=" + options.key,
layer: layers[options.type],
version: '1.0.0',
matrixSet: matrixSets[options.proj],
format: 'tiles',
projection: projection,
requestEncoding: 'KVP',
style: 'default',
tileGrid: wmtsTileGrid
});
let wmtsLayer = new TileLayer({
source: wmtsSource
});
return wmtsLayer
}
再放兩個例子:
這個是使用CGCS2000坐標系的,網(wǎng)上有很多人使用OpenLayers加載不上這個坐標系,是因為通過Proj4這個庫使用EPSG.io上的坐標代碼有bug,Proj4.js的加載不上,改用WKT的數(shù)據(jù)就可以。
import { Map, View } from 'ol';
import { getTianditu } from './js/tianditu'
import { register } from 'ol/proj/proj4';
import proj4 from 'proj4';
proj4.defs("EPSG:4490", "GEOGCS[\"China Geodetic Coordinate System 2000\",DATUM[\"China_2000\",SPHEROID[\"CGCS2000\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"1024\"]],AUTHORITY[\"EPSG\",\"1043\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4490\"]]");
register(proj4);
var map = new Map({
target: "map",
view: new View({
center: [116.391478, 39.903185],
// center: [11936406.337013, 3786384.633134],
projection: "EPSG:4490",
zoom: 5,
maxZoom: 18,
minZoom: 1
})
});
var tdt = getTianditu({
type: '矢量底圖',
// proj: '球面墨卡托投影',
proj: '經(jīng)緯度投影',
key: '用你自己的key'
});
var zz = getTianditu({
type: '矢量注記',
// proj: '球面墨卡托投影',
proj: '經(jīng)緯度投影',
key: '用你自己的key'
})
var jj = getTianditu({
type: '全球境界',
// proj: '球面墨卡托投影',
proj: '經(jīng)緯度投影',
key: '用你自己的key'
})
map.addLayer(tdt)
map.addLayer(zz)
map.addLayer(jj)
下面這個是3857坐標系的:
import { Map, View } from 'ol';
import { getTianditu } from './js/tianditu'
import { register } from 'ol/proj/proj4';
import proj4 from 'proj4';
// proj4.defs("EPSG:4490", "GEOGCS[\"China Geodetic Coordinate System 2000\",DATUM[\"China_2000\",SPHEROID[\"CGCS2000\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"1024\"]],AUTHORITY[\"EPSG\",\"1043\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4490\"]]");
// register(proj4);
var map = new Map({
target: "map",
view: new View({
// center: [116.391478, 39.903185],
center: [11936406.337013, 3786384.633134],
// projection: "EPSG:4490",
zoom: 5,
maxZoom: 18,
minZoom: 1
})
});
var tdt = getTianditu({
type: '矢量底圖',
proj: '球面墨卡托投影',
// proj: '經(jīng)緯度投影',
key: '用你自己的key'
});
var zz = getTianditu({
type: '矢量注記',
proj: '球面墨卡托投影',
// proj: '經(jīng)緯度投影',
key: '用你自己的key'
})
var jj = getTianditu({
type: '全球境界',
proj: '球面墨卡托投影',
// proj: '經(jīng)緯度投影',
key: '用你自己的key'
})
map.addLayer(tdt)
map.addLayer(zz)
map.addLayer(jj)
圖荒的問題暫時得到解決了,關鍵時刻還是要看國家隊……