Skip to content

Commit 3112a13

Browse files
[fix]webmap xyz叠加图层支持添加非3857图层 review by xiongjj
1 parent d11d813 commit 3112a13

File tree

8 files changed

+2339
-2129
lines changed

8 files changed

+2339
-2129
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
/web/
1010
/package-lock.json
1111
.npmrc
12-
/dist/mapboxgl/resources/
12+
/dist/mapboxgl/resources/
13+
/dist/maplibregl/resources/

src/common/mapping/WebMapBase.js

+6
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const WORLD_WIDTH = 360;
4949
* @fires WebMapBase#mapbeforeremove
5050
* @fires WebMapBase#getmapfailed
5151
* @fires WebMapBase#getlayersfailed
52+
* @fires WebMapBase#xyztilelayernotsupport
5253
* @usage
5354
*/
5455
export function createWebMapBaseExtending(SuperClass, { mapRepo }) {
@@ -160,6 +161,11 @@ export function createWebMapBaseExtending(SuperClass, { mapRepo }) {
160161
* @description 底图投影与底图投影不匹配。
161162
*/
162163
'projectionnotmatch',
164+
/**
165+
* @event WebMapBase#xyztilelayernotsupport
166+
* @description XYZ TILE图层与底图的分辨率或原点不匹配。
167+
*/
168+
'xyztilelayernotsupport',
163169
'layeraddchanged',
164170
'layerupdatechanged',
165171
/**

src/common/mapping/WebMapV2.js

+39-3
Original file line numberDiff line numberDiff line change
@@ -687,12 +687,47 @@ export function createWebMapV2Extending(SuperClass, { MapManager, mapRepo, crsMa
687687
}
688688

689689
_createZXYLayer(layerInfo, addedCallback) {
690-
const { url, subdomains, layerID, name, visible } = layerInfo;
690+
const { url, subdomains, layerID, name, visible, tileSize, resolutions, origin, minZoom: minzoom, maxZoom: maxzoom } = layerInfo;
691691
const urls = (subdomains && subdomains.length) ? subdomains.map(item => url.replace('{s}', item)) : [url];
692692
const layerId = layerID || name;
693-
this._addBaselayer({ url: urls, layerID: layerId, visibility: visible });
693+
const isSupport = this._isSupportZXYTileLayer({ resolutions, tileSize, origin });
694+
if (isSupport) {
695+
this._addBaselayer({ url: urls, layerID: layerId, visibility: visible, minzoom, maxzoom, isIserver: false, tileSize });
696+
} else {
697+
this.fire('xyztilelayernotsupport', { error: `The resolutions or origin of layer ${name} on XYZ Tile does not match the map`, error_code: 'XYZ_TILE_LAYER_NOT_SUPPORTED', layer: layerInfo});
698+
}
694699
addedCallback && addedCallback();
695700
}
701+
_isSupportZXYTileLayer({ resolutions, tileSize, origin }) {
702+
const isOldWebMecartor = origin === undefined && resolutions === undefined;
703+
if (isOldWebMecartor) {
704+
return true;
705+
}
706+
return this._isSameOrigin(origin) && this._isSameResolutions(resolutions, tileSize);
707+
}
708+
_isSameOrigin(origin) {
709+
const extent = this.map.getCRS().getExtent();
710+
return origin[0].toFixed(2) === extent[0].toFixed(2) && origin[1].toFixed(2) === extent[3].toFixed(2);
711+
}
712+
_isSameResolutions(resolutions, tileSize, mapTileSize = 512) {
713+
const mapResolutions = this._getMapResolutions();
714+
const conversion = mapTileSize / tileSize;
715+
return resolutions.every((item, i) => (item).toFixed(6) === (conversion * mapResolutions[i]).toFixed(6));
716+
}
717+
_getMapResolutions() {
718+
return this._getResolutionsByExtent({extent: this.map.getCRS().getExtent(), tileSize: 512})
719+
}
720+
_getResolutionsByExtent({ extent, maxZoom = 24, tileSize }) {
721+
const width = extent[2] - extent[0];
722+
const height = extent[3] - extent[1];
723+
const size = width >= height ? width : height;
724+
const maxReolution = size / tileSize;
725+
const resolutions = [];
726+
for (let i = 0; i <= maxZoom; i++) {
727+
resolutions.push(maxReolution / Math.pow(2, i));
728+
}
729+
return resolutions;
730+
}
696731

697732
_createDynamicTiledLayer(layerInfo, addedCallback) {
698733
const url = layerInfo.url;
@@ -2424,14 +2459,15 @@ export function createWebMapV2Extending(SuperClass, { MapManager, mapRepo, crsMa
24242459
minzoom = 0,
24252460
maxzoom = 22,
24262461
isIserver = false,
2462+
tileSize = 256,
24272463
bounds
24282464
}) {
24292465
const source = {
24302466
type: 'raster',
24312467
tiles: url,
24322468
minzoom: minzoom || 0,
24332469
maxzoom: maxzoom || 22,
2434-
tileSize: isIserver ? this.rasterTileSize : 256,
2470+
tileSize: isIserver ? this.rasterTileSize : tileSize,
24352471
rasterSource: isIserver ? 'iserver' : '',
24362472
prjCoordSys:
24372473
isIserver && !this.isOnlineBaseLayer(url[0], this.baseProjection) && +this.baseProjection.split(':')[1] > 0

src/mapboxgl/mapping/WebMap.js

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import { GraticuleLayer } from '../overlay/GraticuleLayer';
6868
* @fires WebMap#dataflowfeatureupdated
6969
* @fires WebMap#projectionnotmatch
7070
* @fires WebMap#mapbeforeremove
71+
* @fires WebMap#xyztilelayernotsupport
7172
* @fires WebMap#getmapfailed
7273
* @fires WebMap#getlayersfailed
7374
* @usage

src/openlayers/mapping/WebMap.js

+51-8
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import * as olLayer from 'ol/layer';
3232
import WMTSCapabilities from 'ol/format/WMTSCapabilities';
3333
import WMSCapabilities from 'ol/format/WMSCapabilities';
3434
import TileGrid from 'ol/tilegrid/TileGrid';
35+
import * as olTilegrid from 'ol/tilegrid';
3536
import WMTSTileGrid from 'ol/tilegrid/WMTS';
3637
import * as olGeometry from 'ol/geom';
3738
import Vector from 'ol/source/Vector';
@@ -988,7 +989,8 @@ export class WebMap extends Observable {
988989
var layer = new olLayer.Tile({
989990
source: source,
990991
zIndex: layerInfo.zIndex || 1,
991-
visible: layerInfo.visible
992+
visible: layerInfo.visible,
993+
...this.getLayerOtherOptions(layerInfo)
992994
});
993995
var layerID = Util.newGuid(8);
994996
if (layerInfo.name) {
@@ -1324,6 +1326,38 @@ export class WebMap extends Observable {
13241326
});
13251327
}
13261328

1329+
getLayerOtherOptions(layerInfo) {
1330+
const { layerType, extent, minZoom, maxZoom } = layerInfo;
1331+
const extentVal = layerType === 'ZXY_TILE' ? this._getZXYTileMapBounds(layerInfo) : extent;
1332+
const options = { extent: extentVal };
1333+
if (typeof minZoom === 'number') {
1334+
options.minZoom = minZoom;
1335+
}
1336+
if (typeof maxZoom === 'number') {
1337+
options.maxZoom = maxZoom;
1338+
}
1339+
return options;
1340+
}
1341+
_getZXYTileMapBounds(layerInfo) {
1342+
const { mapBounds, tileSize = 256, resolutions, origin } = layerInfo;
1343+
if (mapBounds) {
1344+
return mapBounds;
1345+
}
1346+
const getBoundsByResoutions = (maxResolution, origin) => {
1347+
const size = maxResolution * tileSize;
1348+
return [origin[0], origin[1] - size, origin[0] + size, origin[1]];
1349+
};
1350+
1351+
if (resolutions) {
1352+
const maxResolution = resolutions.sort((a, b) => b - a)[0];
1353+
return getBoundsByResoutions(maxResolution, origin);
1354+
}
1355+
// 兼容之前的3857全球剖分
1356+
const projection = this.baseProjection;
1357+
if (projection === 'EPSG:3857') {
1358+
return [-20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892];
1359+
}
1360+
}
13271361
/**
13281362
* @private
13291363
* @function WebMap.prototype.createXYZTileSource
@@ -1332,17 +1366,26 @@ export class WebMap extends Observable {
13321366
* @returns {ol.source.XYZ} xyz的source
13331367
*/
13341368
createXYZTileSource(layerInfo) {
1335-
const { url, subdomains } = layerInfo;
1336-
const urls = (subdomains && subdomains.length) ? subdomains.map(item => url.replace('{s}', item)) : [url];
1337-
const tileGrid = TileSuperMapRest.createTileGrid([-20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892]);
1338-
return new XYZ({
1369+
const { url, subdomains, origin, resolutions, tileSize } = layerInfo;
1370+
const urls = subdomains && subdomains.length ? subdomains.map((item) => url.replace('{s}', item)) : [url];
1371+
const options = {
13391372
urls,
13401373
wrapX: false,
13411374
crossOrigin: 'anonymous',
1342-
tileGrid
1343-
});
1375+
tileGrid: this._getTileGrid({ origin, resolutions, tileSize }),
1376+
projection: this.baseProjection
1377+
};
1378+
return new XYZ(options);
1379+
}
1380+
_getTileGrid({ origin, resolutions, tileSize }) {
1381+
if (origin === undefined && resolutions === undefined) {
1382+
// 兼容上一版webMercator全球剖分
1383+
const extent = [-20037508.3427892, -20037508.3427892, 20037508.3427892, 20037508.3427892];
1384+
return olTilegrid.createXYZ({ extent });
1385+
} else {
1386+
new TileGrid({ origin, resolutions, tileSize });
1387+
}
13441388
}
1345-
13461389
/**
13471390
* @private
13481391
* @function WebMap.prototype.createWMSSource

test/mapboxgl/mapping/WebMapV2Spec.js

+76-7
Original file line numberDiff line numberDiff line change
@@ -1382,8 +1382,6 @@ describe('mapboxgl_WebMapV2', () => {
13821382
datavizWebmap.on('mapcreatesucceeded', callback);
13831383
});
13841384

1385-
1386-
13871385
it('updateOverlayLayer unique', (done) => {
13881386
spyOn(FetchRequest, 'get').and.callFake((url) => {
13891387
if (url.indexOf('portal.json') > -1) {
@@ -1492,7 +1490,7 @@ describe('mapboxgl_WebMapV2', () => {
14921490
});
14931491
});
14941492

1495-
it('add zxytile layer', (done) => {
1493+
it('add zxytile layer 3857全球剖分', (done) => {
14961494
spyOn(FetchRequest, 'get').and.callFake((url) => {
14971495
if (url.indexOf('portal.json') > -1) {
14981496
return Promise.resolve(new Response(JSON.stringify(iportal_serviceProxy)));
@@ -1522,6 +1520,36 @@ describe('mapboxgl_WebMapV2', () => {
15221520
});
15231521
});
15241522

1523+
it('add zxytile layer 4326 world', (done) => {
1524+
spyOn(FetchRequest, 'get').and.callFake((url) => {
1525+
if (url.indexOf('portal.json') > -1) {
1526+
return Promise.resolve(new Response(JSON.stringify(iportal_serviceProxy)));
1527+
} else if (url.indexOf('/map.json') > -1) {
1528+
return Promise.resolve(new Response(datavizWebmap_ZXYTILE_4326));
1529+
}
1530+
return Promise.resolve(new Response(JSON.stringify({})));
1531+
});
1532+
datavizWebmap = new WebMap(
1533+
'test',
1534+
{
1535+
target: 'map',
1536+
serverUrl: 'http://fake/fakeiportal',
1537+
withCredentials: false
1538+
},
1539+
{
1540+
style: {
1541+
version: 8,
1542+
sources: {},
1543+
layers: []
1544+
}
1545+
}
1546+
);
1547+
datavizWebmap.on('mapcreatesucceeded', ({ layers }) => {
1548+
expect(layers.length).toBe(2);
1549+
done();
1550+
});
1551+
});
1552+
15251553
it('isvj-5215', (done) => {
15261554
spyOn(FetchRequest, 'get').and.callFake((url) => {
15271555
if (url.indexOf('portal.json') > -1) {
@@ -2683,28 +2711,69 @@ describe('mapboxgl_WebMapV2', () => {
26832711
});
26842712
});
26852713

2686-
it('initial_xyzLayer', (done) => {
2714+
it('initial_xyzLayer 3857全球剖分', (done) => {
26872715
spyOn(FetchRequest, 'get').and.callFake((url) => {
26882716
if (url.indexOf('map.json') > -1) {
26892717
return Promise.resolve(new Response(JSON.stringify(xyzLayer)));
26902718
} else if (url.indexOf('portal.json') > -1) {
26912719
return Promise.resolve(new Response(JSON.stringify(iportal_serviceProxy)));
26922720
}
2693-
return Promise.resolve();
2721+
return Promise.resolve(new Response(JSON.stringify({})));
26942722
});
26952723
datavizWebmap = new WebMap(id, {
26962724
server: server
26972725
});
26982726
datavizWebmap.on('mapcreatesucceeded', ({ map }) => {
26992727
const layers = map.getStyle().layers;
2700-
expect(layers.length).toBe(1);
2728+
expect(layers.length).toBe(2);
27012729
const xyzLayer = layers[0];
27022730
expect(xyzLayer.id).toBe('OpenStreetMap');
27032731
expect(xyzLayer.type).toBe('raster');
2732+
const xyzLayer1 = layers[1];
2733+
expect(xyzLayer1.id).toBe('xyz');
2734+
expect(xyzLayer1.type).toBe('raster');
2735+
done();
2736+
});
2737+
});
2738+
it('initial_xyzLayer world 4326', (done) => {
2739+
spyOn(FetchRequest, 'get').and.callFake((url) => {
2740+
if (url.indexOf('map.json') > -1) {
2741+
return Promise.resolve(new Response(JSON.stringify(xyzLayer4326)));
2742+
} else if (url.indexOf('portal.json') > -1) {
2743+
return Promise.resolve(new Response(JSON.stringify(iportal_serviceProxy)));
2744+
}
2745+
return Promise.resolve(new Response(JSON.stringify({})));
2746+
});
2747+
datavizWebmap = new WebMap(id, {
2748+
server: server
2749+
});
2750+
datavizWebmap.on('mapcreatesucceeded', ({ map }) => {
2751+
const layers = map.getStyle().layers;
2752+
expect(layers.length).toBe(2);
2753+
const xyzLayer = layers[1];
2754+
expect(xyzLayer.id).toBe('mapboxgl-256x2');
2755+
expect(xyzLayer.type).toBe('raster');
2756+
done();
2757+
});
2758+
});
2759+
it('initial_xyzLayer jingjin 4326', (done) => {
2760+
spyOn(FetchRequest, 'get').and.callFake((url) => {
2761+
if (url.indexOf('map.json') > -1) {
2762+
return Promise.resolve(new Response(JSON.stringify(xyzLayerjingjin4326)));
2763+
} else if (url.indexOf('portal.json') > -1) {
2764+
return Promise.resolve(new Response(JSON.stringify(iportal_serviceProxy)));
2765+
}
2766+
return Promise.resolve();
2767+
});
2768+
datavizWebmap = new WebMap(id, {
2769+
server: server
2770+
});
2771+
datavizWebmap.on('xyztilelayernotsupport', (e) => {
2772+
expect(e.error).toBe(`The resolutions or origin of layer jingjin on XYZ Tile does not match the map`);
2773+
expect(e.error_code).toBe(`XYZ_TILE_LAYER_NOT_SUPPORTED`);
27042774
done();
27052775
});
27062776
});
2707-
27082777
it('initial_mapboxstyleLayer', (done) => {
27092778
spyOn(FetchRequest, 'get').and.callFake((url) => {
27102779
if (url.indexOf('map.json') > -1) {

test/openlayers/mapping/WebMapSpec.js

+24-3
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ describe('openlayers_WebMap', () => {
184184
}
185185
});
186186

187-
it('initialize_ZXYtILE', (done) => {
187+
it('initialize_ZXYtILE 3857全球剖分', (done) => {
188188
let options = {
189189
server: server,
190190
successCallback,
@@ -195,17 +195,38 @@ describe('openlayers_WebMap', () => {
195195
var mapJson = datavizWebmap_ZXYTILE;
196196
return Promise.resolve(new Response(mapJson));
197197
}
198-
return Promise.resolve();
198+
return Promise.resolve(new Response(JSON.stringify({})));
199199
});
200200
var datavizWebmap = new WebMap(id, options);
201201

202202
function successCallback() {
203203
expect(datavizWebmap.mapParams.title).toBe('xyz');
204-
// expect(datavizWebmap.layerAdded).toBe(2);
204+
expect(datavizWebmap.layerAdded).toBe(1);
205205
done();
206206
}
207207
});
208208

209+
it('initialize_ZXYtILE world 4326', (done) => {
210+
let options = {
211+
server: server,
212+
successCallback,
213+
errorCallback: function () { }
214+
};
215+
spyOn(FetchRequest, 'get').and.callFake((url) => {
216+
if (url.indexOf('map.json') > -1) {
217+
var mapJson = datavizWebmap_ZXYTILE_4326;
218+
return Promise.resolve(new Response(mapJson));
219+
}
220+
return Promise.resolve(new Response(JSON.stringify({})));
221+
});
222+
var datavizWebmap = new WebMap(id, options);
223+
function successCallback() {
224+
expect(datavizWebmap.mapParams.title).toBe('4326-zxy-tile');
225+
expect(datavizWebmap.layerAdded).toBe(1);
226+
done();
227+
}
228+
});
229+
209230
it('jsonsql', (done) => {
210231
let options = {
211232
server: server,

0 commit comments

Comments
 (0)