1
1
import maplibregl from 'maplibre-gl' ;
2
+ import { FetchRequest } from '@supermap/iclient-common/util/FetchRequest' ;
2
3
import { MapService } from '../services/MapService' ;
3
- import { InitMapServiceBase , isPlaneProjection , getZoom } from '@supermap/iclient-common/iServer/InitMapServiceBase' ;
4
+ import { InitMapServiceBase , isPlaneProjection , getZoom , getTileset , getTileFormat } from '@supermap/iclient-common/iServer/InitMapServiceBase' ;
4
5
import proj4 from 'proj4' ;
5
6
/**
6
7
* @function initMap
@@ -44,7 +45,11 @@ export function initMap(url, options = {}) {
44
45
return ;
45
46
}
46
47
if ( epsgCode !== 3857 && ! dynamicProjection && ! maplibregl . CRS ) {
47
- reject ( new Error ( `The EPSG code ${ epsgCode } is not yet supported` ) ) ;
48
+ reject (
49
+ new Error (
50
+ `The EPSG code ${ epsgCode } needs to include maplibre-gl-enhance.js. Refer to the example: https://iclient.supermap.io/examples/maplibregl/editor.html#mvtVectorTile_2362`
51
+ )
52
+ ) ;
48
53
return ;
49
54
}
50
55
const mapOptions = await createMapOptions ( url , res . result , { ...options , initMapService } ) ;
@@ -59,6 +64,80 @@ export function initMap(url, options = {}) {
59
64
} ) ;
60
65
}
61
66
67
+ /**
68
+ * @private
69
+ * @function getCrsExtent
70
+ * @description 获取当前坐标系范围,[左,下,右,上]。
71
+ * @param {Object|Array } extent -坐标系范围。
72
+ * @returns {Array }
73
+ */
74
+ function getCRSExtent ( extent ) {
75
+ if ( extent instanceof Array ) {
76
+ return extent ;
77
+ }
78
+ if ( extent . leftBottom && extent . rightTop ) {
79
+ return [ extent . leftBottom . x , extent . leftBottom . y , extent . rightTop . x , extent . rightTop . y ] ;
80
+ }
81
+ return [ extent . left , extent . bottom , extent . right , extent . top ] ;
82
+ }
83
+
84
+ /**
85
+ * @private
86
+ * @function defineCRSByWKT
87
+ * @description 定义crs。
88
+ * @param {string } crsName - 投影名称。
89
+ * @param {string } wkt - wkt。
90
+ * @param {Object } extent - 坐标系范围。
91
+ * @returns {string }
92
+ */
93
+ function defineCRSByWKT ( crsName , wkt , extent ) {
94
+ const crsExtent = getCRSExtent ( extent ) ;
95
+ const defineCRS = new maplibregl . CRS ( crsName , wkt , crsExtent ) ;
96
+ return defineCRS ;
97
+ }
98
+
99
+ /**
100
+ * @private
101
+ * @function transformMapCenter
102
+ * @description 转换center。
103
+ * @param {Object } mapInfoCenter - 中心点。
104
+ * @param {string } baseProjection - 坐标投影。
105
+ * @returns {Array }
106
+ */
107
+ function transformMapCenter ( mapInfoCenter , sourceProjection ) {
108
+ let center = mapInfoCenter ;
109
+ if ( sourceProjection === 'EPSG:3857' ) {
110
+ return proj4 ( sourceProjection , 'EPSG:4326' , mapInfoCenter ) ;
111
+ }
112
+ if ( sourceProjection !== 'EPSG:4326' ) {
113
+ return maplibregl . proj4 ( sourceProjection , 'EPSG:4326' , mapInfoCenter ) ;
114
+ }
115
+ return center ;
116
+ }
117
+
118
+ /**
119
+ * @private
120
+ * @function getVectorTileCRSExtent
121
+ * @description 获取矢量瓦片坐标系范围。
122
+ * @param {string } vectorStyleUrl - 矢量瓦片 style json 服务地址。
123
+ * @param {string } restMapUrl - 矢量瓦片 rest 地图服务地址。
124
+ * @returns {Object }
125
+ */
126
+ async function getVectorTileCRSExtent ( vectorStyleUrl , restMapUrl ) {
127
+ try {
128
+ const vectorStyleDataRes = await FetchRequest . get ( vectorStyleUrl ) ;
129
+ const vectorStyleData = await vectorStyleDataRes . json ( ) ;
130
+ if ( vectorStyleData . metadata && vectorStyleData . metadata . indexbounds ) {
131
+ return { extent : vectorStyleData . metadata . indexbounds } ;
132
+ }
133
+ const vectorExtentDataRes = await FetchRequest . get ( `${ restMapUrl } /prjCoordSys/projection/extent.json` ) ;
134
+ const vectorExtentData = await vectorExtentDataRes . json ( ) ;
135
+ return { extent : vectorExtentData , center : vectorStyleData . center } ;
136
+ } catch ( error ) {
137
+ return { extent : [ ] } ;
138
+ }
139
+ }
140
+
62
141
/**
63
142
* @private
64
143
* @function createMapOptions
@@ -77,22 +156,80 @@ async function createMapOptions(url, resetServiceInfo, options) {
77
156
}
78
157
const sourceType = options . type || 'raster' ;
79
158
const mapOptions = options . mapOptions || { } ;
80
- const { center, bounds, scale, dpi, coordUnit } = resetServiceInfo ;
81
- const mapCenter = center ? proj4 ( 'EPSG:3857' , 'EPSG:4326' , [ center . x , center . y ] ) : [ 0 , 0 ] ;
159
+ const {
160
+ prjCoordSys : { epsgCode } ,
161
+ bounds,
162
+ center,
163
+ dpi,
164
+ coordUnit,
165
+ scale
166
+ } = resetServiceInfo ;
167
+ let mapCenter = center ? [ center . x , center . y ] : [ 0 , 0 ] ;
168
+ let crs = `EPSG:${ epsgCode } ` ;
169
+ let extent = bounds ;
82
170
let tileUrl =
83
171
sourceType === 'vector-tile'
84
172
? url + '/tileFeature/vectorstyles.json?type=MapBox_GL&styleonly=true&tileURLTemplate=ZXY'
85
173
: url ;
86
- let rasterExtraInfo = { } ;
87
- if ( sourceType === 'raster' ) {
88
- const tileSize = 256 ;
89
- rasterExtraInfo . tileSize = tileSize ;
90
- const transparent = mapOptions . transparent !== false ;
91
- tileUrl += `/zxyTileImage.png?z={z}&x={x}&y={y}&width=${ tileSize } &height=${ tileSize } &transparent=${ transparent } ` ;
174
+ let nonEnhanceExtraInfo = { } ;
175
+ let enhanceExtraInfo = { } ;
176
+ let zoom ;
177
+ let tileSize = 512 ;
178
+ let tileFormat = 'png' ;
179
+ if ( maplibregl . CRS ) {
180
+ const baseProjection = crs ;
181
+ const wkt = await options . initMapService . getWKT ( ) ;
182
+ let vectorTileInfo ;
183
+ if ( sourceType === 'vector-tile' ) {
184
+ vectorTileInfo = await getVectorTileCRSExtent ( tileUrl , url ) ;
185
+ extent = vectorTileInfo . extent ;
186
+ }
187
+ crs = defineCRSByWKT ( baseProjection , wkt , extent ) ;
188
+ if ( sourceType === 'raster' ) {
189
+ enhanceExtraInfo . rasterSource = 'iserver' ;
190
+ }
191
+ if ( vectorTileInfo && vectorTileInfo . center ) {
192
+ mapCenter = vectorTileInfo . center ;
193
+ } else {
194
+ mapCenter = transformMapCenter ( mapCenter , baseProjection ) ;
195
+ }
196
+
197
+ const tilesets = await options . initMapService . getTilesets ( ) ;
198
+ const tileset = getTileset ( tilesets . result , { prjCoordSys : resetServiceInfo . prjCoordSys , tileType : 'Image' } ) ;
199
+
200
+ if ( tileset ) {
201
+ tileFormat = getTileFormat ( tileset ) ;
202
+ const maxWidth = Math . max ( tileset . bounds . right - tileset . originalPoint . x , tileset . originalPoint . y - tileset . bounds . bottom ) ;
203
+ const tileCount = maxWidth / ( tileset . resolutions [ 0 ] * 256 ) ;
204
+ zoom = Math . ceil ( Math . log2 ( tileCount ) ) ;
205
+ const closestTileCount = Math . pow ( 2 , zoom ) ;
206
+ const width = closestTileCount * 256 * tileset . resolutions [ 0 ] ;
207
+ const crsBounds = [
208
+ tileset . originalPoint . x ,
209
+ tileset . originalPoint . y - width ,
210
+ tileset . originalPoint . x + width ,
211
+ tileset . originalPoint . y
212
+ ] ;
213
+ crs = new maplibregl . CRS ( baseProjection , crsBounds ) ;
214
+ zoom = zoom - 1 ;
215
+ tileSize = tileset . tileWidth ;
216
+ }
217
+ } else {
218
+ crs = 'EPSG:3857' ;
219
+ mapCenter = transformMapCenter ( mapCenter , crs ) ;
220
+ if ( sourceType === 'raster' ) {
221
+ const tileSize = 256 ;
222
+ nonEnhanceExtraInfo . tileSize = tileSize ;
223
+ const transparent = mapOptions . transparent !== false ;
224
+ tileUrl += `/zxyTileImage.png?z={z}&x={x}&y={y}&width=${ tileSize } &height=${ tileSize } &transparent=${ transparent } ` ;
225
+ }
226
+ }
227
+ if ( zoom === undefined ) {
228
+ zoom = getZoom ( { scale, dpi, coordUnit } , extent ) ;
92
229
}
93
- const zoom = getZoom ( { scale, dpi, coordUnit } , bounds ) ;
94
230
return {
95
231
container : 'map' ,
232
+ crs,
96
233
center : mapCenter ,
97
234
zoom,
98
235
style :
@@ -101,9 +238,12 @@ async function createMapOptions(url, resetServiceInfo, options) {
101
238
version : 8 ,
102
239
sources : {
103
240
'smaples-source' : {
241
+ format : tileFormat ,
242
+ tileSize,
104
243
type : 'raster' ,
105
244
tiles : [ tileUrl ] ,
106
- ...rasterExtraInfo
245
+ ...nonEnhanceExtraInfo ,
246
+ ...enhanceExtraInfo
107
247
}
108
248
} ,
109
249
layers : [
0 commit comments