forked from SuperMap/iClient-JavaScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinitMap.js
More file actions
266 lines (253 loc) · 8.87 KB
/
initMap.js
File metadata and controls
266 lines (253 loc) · 8.87 KB
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/* Copyright© 2000 - 2022 SuperMap Software Co.Ltd. All rights reserved.
* This program are made available under the terms of the Apache License, Version 2.0
* which accompanies this distribution and is available at http://www.apache.org/licenses/LICENSE-2.0.html.*/
import L from 'leaflet';
import { CRS } from '../core/Proj4Leaflet';
import { getZoomByResolution, scalesToResolutions, scaleToResolution } from '../core/Util';
import { NonEarthCRS } from '../core/NonEarthCRS';
import { TiledMapLayer } from './TiledMapLayer';
import { MapService } from '../services/MapService';
import proj4 from 'proj4';
/**
* @function initMap
* @description 根据 SuperMap iServer 服务参数,创建地图与图层。目前仅支持SuperMap iServer 地图服务,创建的图层为 TiledMapLayer。
* @category BaseTypes Util
* @version 11.0.1
* @example
* initMap(url, {mapOptions, layerOptions});
* @param {string} url - 服务地址,例如: http://{ip}:{port}/iserver/services/map-world/rest/maps/World。
* @param {Object} [options] - 参数。
* @param {L.MapOptions} [options.mapOptions] - 地图参数,未设置的情况下,默认使用 SuperMap iServer 服务参数进行设置。
* @param {Object} [options.layerOptions] - 图层参数,参考<a href="TiledMapLayer.html">TiledMapLayer</a>的参数。
* @returns {Promise} Promise 对象,返回{ map, layer }。
* @usage
* ```
* // 浏览器
* <script type="text/javascript" src="{cdn}"></script>
* <script>
* const initMap = {namespace}.initMap;
* initMap(url, {mapOptions, layerOptions});
*
* </script>
* // ES6 Import
* import { initMap } from "{npm}";
*
* initMap(url, {mapOptions, layerOptions});
*
* ```
*/
export function initMap(url, options) {
options = options || {};
const mapOptions = options.mapOptions || {};
const layerOptions = options.layerOptions || {};
return new Promise((resolve, reject) => {
new MapService(url).getMapInfo(async (res) => {
if (res.type === 'processCompleted') {
const { prjCoordSys } = res.result;
const epsgCodeStr = getEpsgCodeStr(prjCoordSys);
if (!isPlaneProjection(prjCoordSys)) {
await setProj(url, epsgCodeStr);
}
const mapInfoOptions = getMapOptions(res.result, mapOptions);
const map = L.map('map', { ...mapInfoOptions, ...mapOptions });
const layer = new TiledMapLayer(url, { ...{ noWrap: true }, ...layerOptions });
layer.addTo(map);
resolve({ map, layer });
return;
}
reject();
});
});
}
/**
* @function crsFromMapJSON
* @description 通过iServer REST地图的配置信息,构建地图的CRS(非平面投影、EPSG:3857、EPSG:4326需要先注册投影)。
* @category BaseTypes Util
* @version 11.0.1
* @param {Object} mapJSONObj - 地图参数。
* @param {Object} mapJSONObj.prjCoordSys - 投影配置。
* @param {Object} mapJSONObj.bounds - 范围。
* @param {number} mapJSONObj.dpi - DPI。
* @param {Array} mapJSONObj.visibleScales - 自定义比例尺。
* @param {Array} mapJSONObj.coordUnit - 地图单位。
* @param {Object} [mapOptions] - 地图参数。
* @param {Object} [mapOptions.maxZoom=22] - 地图最大缩放级别。没有设置固定比例尺时生效。
* @returns {CRS} 返回CRS。
*/
export function crsFromMapJSON(mapJSONObj, mapOptions) {
const { maxZoom = 22 } = mapOptions || {};
const { bounds, prjCoordSys, dpi, visibleScales, coordUnit } = mapJSONObj;
const resolutions = scalesToResolutions(visibleScales, bounds, dpi, coordUnit, maxZoom);
if (isPlaneProjection(prjCoordSys)) {
return getNonEarthCRS(bounds);
}
const epsgCodeStr = getEpsgCodeStr(prjCoordSys);
if (!hasRegisterProj(epsgCodeStr)) {
return;
}
return getCRS(epsgCodeStr, { bounds, dpi, resolutions });
}
/**
* @private
* @function isPlaneProjection
* @description 是否是平面坐标系。
* @param {Object} prjCoordSys - prjCoordSys
* @returns {boolean}
*/
function isPlaneProjection(prjCoordSys) {
return prjCoordSys.type === 'PCS_NON_EARTH';
}
/**
* @private
* @function setProj
* @description 注册4214 4610 4490等投影。
* @param {string} url
* @param {string} epsgCodeStr - epsgCode。
*/
async function setProj(url, epsgCodeStr) {
if (!hasRegisterProj(epsgCodeStr, false)) {
const def = await getWKT(url);
def && proj4.defs(epsgCodeStr, def);
}
}
/**
* @private
* @function hasRegisterProj
* @description 判断是否注册了投影。
* @param {string} epsgCodeStr - epsgCode。
* @param {boolean} isConsole - 是否在控制台打印。
* @returns {boolean}
*/
function hasRegisterProj(epsgCodeStr, isConsole = true) {
try {
proj4(epsgCodeStr);
} catch (e) {
if (isConsole) {
console.error(
`The projection of ${epsgCodeStr} is missing, please register the projection of ${epsgCodeStr} first, refer to the documentation: https://iclient.supermap.io/web/introduction/leafletDevelop.html#multiProjection`
);
}
return false;
}
return true;
}
/**
* @private
* @function getMapOptions
* @description 获取地图参数。
* @param {Object} mapJSONObj - 地图 JSON 对象。
* @param {Object} [mapOptions] - 地图参数。
* @param {Object} [mapOptions.maxZoom=22] - 地图最大缩放级别(没有设置固定比例尺时生效)。
* @returns {Object} mapParams。
*/
function getMapOptions(mapJSONObj, mapOptions) {
const { bounds, center, scale, visibleScales, prjCoordSys, dpi, coordUnit } = mapJSONObj;
const { maxZoom = 22 } = mapOptions;
const resolutions = scalesToResolutions(visibleScales, bounds, dpi, coordUnit, maxZoom);
const crs = crsFromMapJSON({ prjCoordSys, bounds, dpi, visibleScales, coordUnit }, { maxZoom });
const visableResolutions = crs.resolutions || resolutions;
const mapParams = {
crs,
center: getCenter(crs, { center, bounds }),
zoom: getZoomByScale({ scale, dpi, coordUnit }, visableResolutions),
maxZoom: getMaxZoom(resolutions)
};
return mapParams;
}
/**
* @private
* @function getZoomByScale
* @description 获取Zoom。
* @param {Object} options
* @param {string} options.scale - scale。
* @param {number} options.dpi - dpi
* @param {string} options.coordUnit - coordUnit
* @param {Object} visableResolutions - visableResolutions
* @returns {number} zoom。
*/
function getZoomByScale({ scale, dpi, coordUnit }, visableResolutions) {
const resolution = scaleToResolution(scale, dpi, coordUnit);
return getZoomByResolution(resolution, visableResolutions);
}
/**
* @private
* @function getMaxZoom
* @description 获取maxZoom。
* @param {Array} visibleResolutions - visibleResolutions
* @returns {number} maxZoom。
*/
function getMaxZoom(visibleResolutions) {
if (visibleResolutions.length > 0) {
return visibleResolutions.length - 1;
}
return 22;
}
/**
* @private
* @function getCenter
* @description 获取center。
* @param {CRS} crs - crs。
* @param {Object} mapJSONObj - 地图 JSON 对象。
* @param {Object} mapJSONObj.center - 地图参数。
* @param {Object} mapJSONObj.bounds - 地图最大缩放级别。
* @returns {Object} center。
*/
function getCenter(crs, { center, bounds }) {
const code = typeof crs === 'string' ? crs : crs.code;
if (typeof center.x !== 'number' && typeof center.y !== 'number') {
center = { lat: (bounds.bottom + bounds.top) / 2, lng: (bounds.left + bounds.right) / 2 };
}
if (code === 'EPSG:4326') {
return { lat: center.y, lng: center.x };
}
return crs.unproject(L.point(center.x, center.y));
}
/**
* @private
* @function getCenter
* @description 获取center。
* @param {Object} prjCoordSys
* @returns {string} center。
*/
function getEpsgCodeStr(prjCoordSys) {
const { type, epsgCode } = prjCoordSys;
if (type == 'PCS_NON_EARTH') {
// 平面投影
return '';
}
return 'EPSG:' + epsgCode;
}
async function getWKT(url) {
return new Promise((resolve, reject) => {
new MapService(url, { withoutFormatSuffix: true }).getWkt((res) => {
if (res.type === 'processCompleted') {
const proj4def = res.result.data;
resolve(proj4def);
return;
}
reject();
});
});
}
function getNonEarthCRS(bounds) {
let options = {
bounds: L.bounds([bounds.left, bounds.bottom], [bounds.right, bounds.top]),
origin: L.point(bounds.left, bounds.top)
};
return new NonEarthCRS(options);
}
function getCRS(epsgCodeStr, { bounds, dpi, resolutions }) {
const wrapLngLeft = proj4(epsgCodeStr, 'EPSG:4326').forward([bounds.left, 0], true);
const wrapLngRight = proj4(epsgCodeStr, 'EPSG:4326').forward([bounds.right, 0], true);
const wrapLng = [parseInt(wrapLngLeft[0]), parseInt(wrapLngRight[0])];
let options = {
wrapLng,
bounds: L.bounds([bounds.left, bounds.bottom], [bounds.right, bounds.top]),
origin: [bounds.left, bounds.top],
dpi: dpi
};
if (resolutions && resolutions.length > 0) {
options.resolutions = resolutions;
}
return new CRS(epsgCodeStr, options);
}