11import maplibregl from 'maplibre-gl' ;
2+ import { FetchRequest } from '@supermap/iclient-common/util/FetchRequest' ;
23import { 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' ;
45import proj4 from 'proj4' ;
56/**
67 * @function initMap
@@ -44,7 +45,11 @@ export function initMap(url, options = {}) {
4445 return ;
4546 }
4647 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+ ) ;
4853 return ;
4954 }
5055 const mapOptions = await createMapOptions ( url , res . result , { ...options , initMapService } ) ;
@@ -59,6 +64,80 @@ export function initMap(url, options = {}) {
5964 } ) ;
6065}
6166
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+
62141/**
63142 * @private
64143 * @function createMapOptions
@@ -77,22 +156,80 @@ async function createMapOptions(url, resetServiceInfo, options) {
77156 }
78157 const sourceType = options . type || 'raster' ;
79158 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 ;
82170 let tileUrl =
83171 sourceType === 'vector-tile'
84172 ? url + '/tileFeature/vectorstyles.json?type=MapBox_GL&styleonly=true&tileURLTemplate=ZXY'
85173 : 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 ) ;
92229 }
93- const zoom = getZoom ( { scale, dpi, coordUnit } , bounds ) ;
94230 return {
95231 container : 'map' ,
232+ crs,
96233 center : mapCenter ,
97234 zoom,
98235 style :
@@ -101,9 +238,12 @@ async function createMapOptions(url, resetServiceInfo, options) {
101238 version : 8 ,
102239 sources : {
103240 'smaples-source' : {
241+ format : tileFormat ,
242+ tileSize,
104243 type : 'raster' ,
105244 tiles : [ tileUrl ] ,
106- ...rasterExtraInfo
245+ ...nonEnhanceExtraInfo ,
246+ ...enhanceExtraInfo
107247 }
108248 } ,
109249 layers : [
0 commit comments