Skip to content

Commit 1ef924b

Browse files
【update】ol 支持加载包含相对地址的style review by luox
1 parent 160e53d commit 1ef924b

File tree

9 files changed

+732
-483
lines changed

9 files changed

+732
-483
lines changed

src/common/commontypes/Util.js

+28
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,34 @@ const Util = {
11101110
}
11111111
rgba.push(opacity);
11121112
return "rgba(" + rgba.join(",") + ")";
1113+
},
1114+
/**
1115+
* @description 是否是绝对地址。
1116+
* @private
1117+
* @param {string} url - 验证地址。
1118+
* @returns {boolean} 是否是绝对地址。
1119+
*/
1120+
isAbsoluteURL(url) {
1121+
try {
1122+
const res = new URL(url);
1123+
return !!res;
1124+
} catch (_) {
1125+
return false;
1126+
}
1127+
},
1128+
/**
1129+
* @description 相对地址转绝对地址。
1130+
* @private
1131+
* @param {string} url - 相对地址。
1132+
* @param {string} base - 基础地址。
1133+
* @returns {string} 完整地址。
1134+
*/
1135+
relative2absolute(url, base) {
1136+
let newUrl = new URL(url, base);
1137+
if (newUrl && newUrl.href) {
1138+
return decodeURIComponent(newUrl.href);
1139+
}
1140+
return;
11131141
}
11141142
};
11151143

src/common/mapping/WebMapV2.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ export function createWebMapV2Extending(SuperClass, { MapManager, mapRepo, crsMa
334334
style.layers.forEach(layer => {
335335
layer.layout && (layer.layout.visibility = this._getVisibility(layerInfo.visible));
336336
});
337-
this.map.addStyle(style);
337+
this.map.addStyle(style, undefined, undefined, undefined, url);
338338
const layerIds = [];
339339
style.layers.forEach((item) => {
340340
if (item.type !== 'background') {

src/openlayers/mapping/WebMap.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -5164,10 +5164,16 @@ export class WebMap extends Observable {
51645164
const envelope = this.getEnvelope(indexbounds, layerInfo.bounds);
51655165
const styleResolutions = this.getStyleResolutions(envelope);
51665166
// const origin = [envelope.left, envelope.top];
5167-
let withCredentials = this.isIportalProxyServiceUrl(styles.sprite);
5168-
const requestParameters = this.tileRequestParameters && this.tileRequestParameters(styles.sprite);
5167+
let baseUrl = layerInfo.url && layerInfo.url.split('?')[0];
5168+
let spriteUrl = styles.sprite;
5169+
if (!CommonUtil.isAbsoluteURL(styles.sprite)) {
5170+
spriteUrl = CommonUtil.relative2absolute(styles.sprite, baseUrl);
5171+
}
5172+
let withCredentials = this.isIportalProxyServiceUrl(spriteUrl);
5173+
const requestParameters = this.tileRequestParameters && this.tileRequestParameters(spriteUrl);
51695174
// 创建MapBoxStyle样式
51705175
let mapboxStyles = new MapboxStyles({
5176+
baseUrl,
51715177
style: styles,
51725178
source: styles.name,
51735179
resolutions: styleResolutions,
@@ -5183,6 +5189,7 @@ export class WebMap extends Observable {
51835189
//设置避让参数
51845190
declutter: true,
51855191
source: new VectorTileSuperMapRest({
5192+
baseUrl,
51865193
style: styles,
51875194
withCredentials,
51885195
projection: layerInfo.projection,

src/openlayers/overlay/VectorTileSuperMapRest.js

+106-85
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import decryptTileUtil from '@supermapgis/tile-decryptor';
2929
* @modulecategory Overlay
3030
* @param {Object} options - 参数。
3131
* @param {(string|undefined)} options.url - 服务地址。
32+
* @param {string} [options.baseUrl] - 当传入 style 对象且 style 中包含了相对路径时,需要传入 baseUrl 来拼接资源路径。
3233
* @param {(string|Object|undefined)} options.style - Mapbox Style JSON 对象或获取 Mapbox Style JSON 对象的 URL。当 `options.format` 为 {@link ol.format.MVT} 且 `options.source` 不为空时有效,优先级高于 `options.url`。
3334
* @param {(string|undefined)} options.source - Mapbox Style JSON 对象中的 source 名称。当 `options.style` 设置时有效。当不配置时,默认为 Mapbox Style JSON 的 `sources` 对象中的第一个。
3435
* @param {(string|Object)} [options.attributions='Tile Data <span>© <a href='http://support.supermap.com.cn/product/iServer.aspx' target='_blank'>SuperMap iServer</a></span> with <span>© <a href='https://iclient.supermap.io' target='_blank'>SuperMap iClient</a></span>'] - 版权描述信息。
@@ -80,6 +81,7 @@ export class VectorTileSuperMapRest extends VectorTile {
8081
me.withCredentials = options.withCredentials;
8182
me.headers = options.headers || {};
8283
me._tileType = options.tileType || 'ScaleXY';
84+
me.baseUrl = options.baseUrl;
8385
this.vectorTileStyles = new VectorTileStyles();
8486
this._initialized(options);
8587

@@ -140,10 +142,10 @@ export class VectorTileSuperMapRest extends VectorTile {
140142
if (!tileCoord) {
141143
return undefined;
142144
} else {
143-
return me._tileUrl
145+
return me._tileUrl
144146
.replace(zRegEx, tileCoord[0].toString())
145147
.replace(xRegEx, tileCoord[1].toString())
146-
.replace(yRegEx, function () {
148+
.replace(yRegEx, function () {
147149
var y = ['4', '5'].indexOf(Util.getOlVersion()) > -1 ? -tileCoord[2] - 1 : tileCoord[2];
148150
return y.toString();
149151
})
@@ -169,7 +171,7 @@ export class VectorTileSuperMapRest extends VectorTile {
169171
var height = Number(tileUrl.match(regHeight)[2]);
170172
var me = this;
171173
tile.setLoader(function (extent, resolution, projection) {
172-
FetchRequest.get(tileUrl, null, {headers:me.headers})
174+
FetchRequest.get(tileUrl, null, { headers: me.headers })
173175
.then(function (response) {
174176
if (tile.getFormat() instanceof GeoJSON) {
175177
return response.json();
@@ -254,49 +256,49 @@ export class VectorTileSuperMapRest extends VectorTile {
254256
}
255257
xhr.withCredentials = me.withCredentials;
256258
for (const key in me.headers) {
257-
if (me.headers.hasOwnProperty(key)) {
258-
xhr.setRequestHeader(key, me.headers[key]);
259-
}
259+
if (me.headers.hasOwnProperty(key)) {
260+
xhr.setRequestHeader(key, me.headers[key]);
261+
}
260262
}
261263
xhr.onload = function () {
262-
if (!xhr.status || (xhr.status >= 200 && xhr.status < 300)) {
263-
const type = format.getType();
264-
let source = void 0;
265-
if (type === 'json' || type === 'text') {
266-
source = xhr.responseText;
267-
} else if (type === 'xml') {
268-
source = xhr.responseXML;
269-
if (!source) {
270-
source = new DOMParser().parseFromString(xhr.responseText, 'application/xml');
271-
}
272-
} else if (type === 'arraybuffer') {
273-
source = xhr.response;
274-
}
275-
if (source) {
276-
source = me._decryptMvt(source);
277-
if (['4', '5'].indexOf(Util.getOlVersion()) > -1) {
278-
success.call(
279-
this,
280-
format.readFeatures(source, { featureProjection: projection }),
281-
format.readProjection(source),
282-
format.getLastExtent()
283-
);
284-
} else {
285-
success.call(
286-
this,
287-
format.readFeatures(source, {
288-
extent: extent,
289-
featureProjection: projection
290-
}),
291-
format.readProjection(source)
292-
);
293-
}
264+
if (!xhr.status || (xhr.status >= 200 && xhr.status < 300)) {
265+
const type = format.getType();
266+
let source = void 0;
267+
if (type === 'json' || type === 'text') {
268+
source = xhr.responseText;
269+
} else if (type === 'xml') {
270+
source = xhr.responseXML;
271+
if (!source) {
272+
source = new DOMParser().parseFromString(xhr.responseText, 'application/xml');
273+
}
274+
} else if (type === 'arraybuffer') {
275+
source = xhr.response;
276+
}
277+
if (source) {
278+
source = me._decryptMvt(source);
279+
if (['4', '5'].indexOf(Util.getOlVersion()) > -1) {
280+
success.call(
281+
this,
282+
format.readFeatures(source, { featureProjection: projection }),
283+
format.readProjection(source),
284+
format.getLastExtent()
285+
);
286+
} else {
287+
success.call(
288+
this,
289+
format.readFeatures(source, {
290+
extent: extent,
291+
featureProjection: projection
292+
}),
293+
format.readProjection(source)
294+
);
295+
}
296+
} else {
297+
failure.call(this);
298+
}
294299
} else {
295-
failure.call(this);
300+
failure.call(this);
296301
}
297-
} else {
298-
failure.call(this);
299-
}
300302
}.bind(this);
301303
xhr.onerror = function () {
302304
failure.call(this);
@@ -307,35 +309,54 @@ export class VectorTileSuperMapRest extends VectorTile {
307309
}
308310

309311
async _initialized(options) {
310-
if (options.format instanceof MVT && options.style) {
311-
let style = options.style;
312-
if (Object.prototype.toString.call(options.style) == '[object String]') {
313-
var url = SecurityManager.appendCredential(options.style);
314-
const response = await FetchRequest.get(url, null, {
315-
withCredentials: options.withCredentials,
316-
headers: options.headers
317-
});
318-
style = await response.json();
319-
}
320-
this._fillByStyleJSON(style, options.source);
321-
} else {
322-
this._fillByRestMapOptions(options.url, options);
323-
}
324-
if (options.format instanceof MVT) {
325-
if (options.decrypt) {
326-
await this._verifyVectorTileIsEncrypt(options);
312+
if (options.format instanceof MVT && options.style) {
313+
let style = options.style;
314+
if (Object.prototype.toString.call(options.style) == '[object String]') {
315+
var url = SecurityManager.appendCredential(options.style);
316+
const response = await FetchRequest.get(url, null, {
317+
withCredentials: options.withCredentials,
318+
headers: options.headers
319+
});
320+
style = await response.json();
321+
}
322+
await this._fillByStyleJSON(style, options.source);
323+
} else {
324+
this._fillByRestMapOptions(options.url, options);
325+
}
326+
if (options.format instanceof MVT) {
327+
if (options.decrypt) {
328+
await this._verifyVectorTileIsEncrypt(options);
329+
}
330+
this.setState('ready');
327331
}
328-
this.setState('ready');
329-
}
330332
}
331333

332-
_fillByStyleJSON(style, source) {
334+
async _fillByStyleJSON(style, source) {
333335
if (!source) {
334336
source = Object.keys(style.sources)[0];
335337
}
338+
//ToDo 支持多个tiles地址
336339
if (style.sources && style.sources[source]) {
337-
//ToDo 支持多个tiles地址
338-
this._tileUrl = SecurityManager.appendCredential(style.sources[source].tiles[0]);
340+
let newUrl;
341+
if (style.sources[source].tiles) {
342+
newUrl = style.sources[source].tiles[0];
343+
if (!CommonUtil.isAbsoluteURL(newUrl)) {
344+
newUrl = CommonUtil.relative2absolute(newUrl, this.baseUrl);
345+
}
346+
} else if (style.sources[source].url) {
347+
let tiles = style.sources[source].url;
348+
if (!CommonUtil.isAbsoluteURL(tiles)) {
349+
tiles = CommonUtil.relative2absolute(tiles, this.baseUrl);
350+
}
351+
const response = await FetchRequest.get(tiles, {}, { withoutFormatSuffix: true });
352+
const sourceInfo = await response.json();
353+
let tileUrl = sourceInfo.tiles[0];
354+
if (!CommonUtil.isAbsoluteURL(tileUrl)) {
355+
tileUrl = CommonUtil.relative2absolute(tileUrl, tiles);
356+
}
357+
newUrl = SecurityManager.appendCredential(tileUrl);
358+
}
359+
this._tileUrl = SecurityManager.appendCredential(newUrl);
339360
}
340361
if (style.metadata && style.metadata.indexbounds) {
341362
const indexbounds = style.metadata.indexbounds;
@@ -390,32 +411,32 @@ export class VectorTileSuperMapRest extends VectorTile {
390411
}
391412

392413
async _verifyVectorTileIsEncrypt(options) {
393-
try {
394-
let serviceUrl = options.url || typeof options.style === 'string' && options.style;
414+
try {
415+
let serviceUrl = options.url || typeof options.style === 'string' && options.style;
395416

396-
if (!serviceUrl && Object.prototype.toString.call(options.style) == '[object Object]') {
397-
const firstSource = Object.keys(options.style.sources)[0];
398-
serviceUrl = options.style.sources[firstSource].tiles[0];
399-
}
400-
const res = await getServiceKey(serviceUrl);
401-
if (res) {
402-
this.decryptOptions = {
403-
key: res.serviceKey,
404-
algorithm: res.algorithm,
405-
decrypt: typeof options.decrypt === 'boolean' ? undefined : options.decrypt,
406-
decryptCompletedFunction: options.decryptCompletedFunction
407-
};
417+
if (!serviceUrl && Object.prototype.toString.call(options.style) == '[object Object]') {
418+
const firstSource = Object.keys(options.style.sources)[0];
419+
serviceUrl = options.style.sources[firstSource].tiles[0];
420+
}
421+
const res = await getServiceKey(serviceUrl);
422+
if (res) {
423+
this.decryptOptions = {
424+
key: res.serviceKey,
425+
algorithm: res.algorithm,
426+
decrypt: typeof options.decrypt === 'boolean' ? undefined : options.decrypt,
427+
decryptCompletedFunction: options.decryptCompletedFunction
428+
};
429+
}
430+
} catch (error) {
431+
console.error(error);
408432
}
409-
} catch (error) {
410-
console.error(error);
411-
}
412433
}
413434

414435
_decryptMvt(mvtData) {
415-
if (this.decryptOptions) {
416-
return decryptTileUtil({ ...this.decryptOptions, arrayBuffer: mvtData });
417-
}
418-
return mvtData;
436+
if (this.decryptOptions) {
437+
return decryptTileUtil({ ...this.decryptOptions, arrayBuffer: mvtData });
438+
}
439+
return mvtData;
419440
}
420441

421442
/**

0 commit comments

Comments
 (0)