Skip to content

Commit 30d920d

Browse files
对接 mapbox maplibre initmap tileset, add maplibre initmap 多坐标系
1 parent 70ee4ae commit 30d920d

File tree

6 files changed

+274
-20
lines changed

6 files changed

+274
-20
lines changed

src/common/iServer/InitMapServiceBase.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,10 @@ export function getTileFormat(tileset) {
140140
*/
141141

142142
export function getTileset(tilesets = [], targets) {
143-
const imageTilesets = tilesets.filter((i) => {
143+
const imageTilesets = Array.isArray(tilesets) && tilesets.filter((i) => {
144144
return i.metaData.tileType === targets.tileType || 'Image' && getEpsgCode(i.metaData.prjCoordSys) === getEpsgCode(targets.prjCoordSys);
145145
});
146-
return imageTilesets[0] && imageTilesets[0].metaData;
146+
return imageTilesets && imageTilesets[0] && imageTilesets[0].metaData;
147147
}
148148

149149

src/mapboxgl/mapping/InitMap.js

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import mapboxgl from 'mapbox-gl';
22
import { MapService } from '../services/MapService';
33
import { FetchRequest } from '@supermap/iclient-common/util/FetchRequest';
4-
import { InitMapServiceBase, isPlaneProjection, getZoom } from '@supermap/iclient-common/iServer/InitMapServiceBase';
4+
import { InitMapServiceBase, isPlaneProjection, getZoom, getTileset, getTileFormat } from '@supermap/iclient-common/iServer/InitMapServiceBase';
55
import proj4 from 'proj4';
66

77
/**
@@ -180,6 +180,9 @@ async function createMapOptions(url, resetServiceInfo, options) {
180180
: url;
181181
let nonEnhanceExtraInfo = {};
182182
let enhanceExtraInfo = {};
183+
let zoom;
184+
let tileSize = 512;
185+
let tileFormat = 'png';
183186
if (mapboxgl.CRS) {
184187
const baseProjection = crs;
185188
const wkt = await options.initMapService.getWKT();
@@ -197,6 +200,27 @@ async function createMapOptions(url, resetServiceInfo, options) {
197200
} else {
198201
mapCenter = transformMapCenter(mapCenter, baseProjection);
199202
}
203+
204+
const tilesets = await options.initMapService.getTilesets();
205+
const tileset = getTileset(tilesets.result, { prjCoordSys: resetServiceInfo.prjCoordSys, tileType: 'Image' });
206+
207+
if (tileset) {
208+
tileFormat = getTileFormat(tileset);
209+
const maxWidth = Math.max(tileset.bounds.right - tileset.originalPoint.x, tileset.originalPoint.y - tileset.bounds.bottom);
210+
const tileCount = maxWidth / (tileset.resolutions[0] * 256);
211+
zoom = Math.ceil(Math.log2(tileCount));
212+
const closestTileCount = Math.pow(2, zoom);
213+
const width = closestTileCount * 256 * tileset.resolutions[0];
214+
const crsBounds = [
215+
tileset.originalPoint.x,
216+
tileset.originalPoint.y - width,
217+
tileset.originalPoint.x + width,
218+
tileset.originalPoint.y
219+
];
220+
crs = new mapboxgl.CRS(baseProjection, crsBounds);
221+
zoom = zoom - 1;
222+
tileSize = tileset.tileWidth;
223+
}
200224
} else {
201225
crs = 'EPSG:3857';
202226
mapCenter = transformMapCenter(mapCenter, crs);
@@ -207,7 +231,9 @@ async function createMapOptions(url, resetServiceInfo, options) {
207231
tileUrl += `/zxyTileImage.png?z={z}&x={x}&y={y}&width=${tileSize}&height=${tileSize}&transparent=${transparent}`;
208232
}
209233
}
210-
const zoom = getZoom({ scale, dpi, coordUnit }, extent);
234+
if (zoom === undefined) {
235+
zoom = getZoom({ scale, dpi, coordUnit }, extent);
236+
}
211237
return {
212238
container: 'map',
213239
crs,
@@ -219,6 +245,8 @@ async function createMapOptions(url, resetServiceInfo, options) {
219245
version: 8,
220246
sources: {
221247
'smaples-source': {
248+
format: tileFormat,
249+
tileSize,
222250
type: 'raster',
223251
tiles: [tileUrl],
224252
...nonEnhanceExtraInfo,

src/mapboxgl/mapping/webmap/v3/WebMap.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,7 @@ export class WebMap extends mapboxgl.Evented {
878878
* @description 获取图层字体类型。
879879
*/
880880
_getLabelFontFamily() {
881-
const fonts = [];
881+
const fonts = ['sans-serif'];
882882
const layers = this._mapInfo.layers;
883883
if (layers && layers.length > 0) {
884884
layers.forEach((layer) => {

src/maplibregl/mapping/InitMap.js

Lines changed: 152 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import maplibregl from 'maplibre-gl';
2+
import { FetchRequest } from '@supermap/iclient-common/util/FetchRequest';
23
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';
45
import 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: [

test/mapboxgl/mapping/InitMapSpec.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,35 @@ describe('mapboxgl_InitMap', () => {
223223
delete mapboxgl.CRS;
224224
delete mapboxgl.proj4;
225225
});
226+
227+
it('with tilesets', (done) => {
228+
const mapServiceInfo = {
229+
dynamicProjection: false,
230+
prjCoordSys: {
231+
epsgCode: 4326
232+
}
233+
};
234+
var tilesetServeRequest = 'http://supermapiserver:8090/iserver/services/map-world/rest/maps/Jinjing111';
235+
spyOn(FetchRequest, 'get').and.callFake((url) => {
236+
if (url.indexOf('Jinjing111') > -1 && url.indexOf('tilesets') === -1) {
237+
return Promise.resolve(new Response(mapInfo_2));
238+
}
239+
if (url.indexOf('Jinjing111/tilesets') > -1) {
240+
return Promise.resolve(new Response(tilesetInfo_1));
241+
}
242+
return Promise.resolve();
243+
});
244+
mapboxgl.CRS = function () {
245+
return {
246+
code: mapServiceInfo.prjCoordSys.epsgCode
247+
};
248+
};
249+
mapboxgl.proj4 = function () {
250+
return [0, 0];
251+
};
252+
initMap(tilesetServeRequest).then(({ map }) => {
253+
expect(map).not.toBeNull();
254+
done();
255+
});
256+
});
226257
});

0 commit comments

Comments
 (0)