原文链接及内容

运行界面

这个例子展示了栅格数据从默认投影(OSM默认投影EPSG:3857)与在MapTiler Cloud Coordinates API中搜索到的任意投影之间的重投影功能。(注:在使用此示例时,请确保在https://www.maptiler.com/cloud/ 上获得您自己的API密钥。)

main.js代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import Graticule from 'ol/layer/Graticule.js';
import Map from 'ol/Map.js';
import OSM from 'ol/source/OSM.js';
import Stroke from 'ol/style/Stroke.js';
import TileDebug from 'ol/source/TileDebug.js';
import TileLayer from 'ol/layer/Tile.js';
import View from 'ol/View.js';
import proj4 from 'proj4';
import {applyTransform} from 'ol/extent.js';
import {get as getProjection, getTransform} from 'ol/proj.js';
import {register} from 'ol/proj/proj4.js';

const osmSource = new OSM();

const debugLayer = new TileLayer({
source: new TileDebug({
tileGrid: osmSource.getTileGrid(),
projection: osmSource.getProjection(),
}),
visible: false,
});

const graticule = new Graticule({
// the style to use for the lines, optional.
strokeStyle: new Stroke({
color: 'rgba(255,120,0,0.9)',
width: 2,
lineDash: [0.5, 4],
}),
showLabels: true,
visible: false,
wrapX: false,
});

const map = new Map({
layers: [
new TileLayer({
source: osmSource,
}),
debugLayer,
graticule,
],
target: 'map',
view: new View({
projection: 'EPSG:3857',
center: [0, 0],
zoom: 1,
}),
});

const queryInput = document.getElementById('epsg-query');
const searchButton = document.getElementById('epsg-search');
const resultSpan = document.getElementById('epsg-result');
const renderEdgesCheckbox = document.getElementById('render-edges');
const showTilesCheckbox = document.getElementById('show-tiles');
const showGraticuleCheckbox = document.getElementById('show-graticule');

function setProjection(code, name, proj4def, bbox) {
if (code === null || name === null || proj4def === null || bbox === null) {
resultSpan.innerHTML = 'Nothing usable found, using EPSG:3857...';
map.setView(
new View({
projection: 'EPSG:3857',
center: [0, 0],
zoom: 1,
}),
);
return;
}

resultSpan.innerHTML = '(' + code + ') ' + name;

proj4.defs(code, proj4def);
register(proj4);
const newProj = getProjection(code);
const fromLonLat = getTransform('EPSG:4326', newProj);

newProj.setWorldExtent(bbox);

// approximate calculation of projection extent,
// checking if the world extent crosses the dateline
if (bbox[0] > bbox[2]) {
bbox[2] += 360;
}
const extent = applyTransform(bbox, fromLonLat, undefined, 8);
newProj.setExtent(extent);
const newView = new View({
projection: newProj,
});
map.setView(newView);
newView.fit(extent);
}

function search(query) {
resultSpan.innerHTML = 'Searching ...';
fetch(
`https://api.maptiler.com/coordinates/search/${query}.json?exports=true&key=Get your own API key at https://www.maptiler.com/cloud/`,
)
.then(function (response) {
return response.json();
})
.then(function (json) {
const results = json['results'];
if (results && results.length > 0) {
for (let i = 0, ii = results.length; i < ii; i++) {
const result = results[i];
if (result) {
const id = result['id'];
const code = id['authority'] + ':' + id['code'];
const name = result['name'];
const proj4def = result['exports']['wkt'];
const bbox = result['bbox'];
if (
code &&
code.length > 0 &&
proj4def &&
proj4def.length > 0 &&
bbox &&
bbox.length == 4
) {
setProjection(code, name, proj4def, bbox);
return;
}
}
}
}
setProjection(null, null, null, null);
});
}

/**
* Handle click event.
* @param {Event} event The event.
*/
searchButton.onclick = function (event) {
search(queryInput.value);
event.preventDefault();
};

/**
* Handle checkbox change events.
*/
function onReprojectionChange() {
osmSource.setRenderReprojectionEdges(renderEdgesCheckbox.checked);
}
function onGraticuleChange() {
graticule.setVisible(showGraticuleCheckbox.checked);
}
function onTilesChange() {
debugLayer.setVisible(showTilesCheckbox.checked);
}
showGraticuleCheckbox.addEventListener('change', onGraticuleChange);
renderEdgesCheckbox.addEventListener('change', onReprojectionChange);
showTilesCheckbox.addEventListener('change', onTilesChange);

onReprojectionChange();
onGraticuleChange();
onTilesChange();

界面布局文件index.html代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Reprojection with coordinate system search</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="node_modules/ol/ol.css">
<style>
.map {
width: 100%;
height: 400px;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<form class="row">
<span class="col-auto">
<span class="input-group">
<label class="input-group-text" for="epsg-query">Search projection:&nbsp</label>
<input type="text" id="epsg-query" placeholder="4326, 27700, 3031, US National Atlas, Swiss, France, ..." class="form-control" size="50" />
<button class="btn btn-outline-secondary" id="epsg-search">Search</button>
</span>
</span>
<span class="mt-2" id="epsg-result">&nbsp;</span>
</form>
<form>
<div class="form-check mt-2">
<input class="form-check-input" type="checkbox" id="render-edges" />
<label class="form-check-label" for="render-edges">Render reprojection edges</label><br>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="show-tiles" />
<label class="form-check-label" for="show-tiles">Show tile coordinates</label><br>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="show-graticule" />
<label class="form-check-label" for="show-graticule">Show graticule</label>
</div>
</form>

<script type="module" src="main.js"></script>
</body>
</html>