Skip to content

Commit 0f200b2

Browse files
committed
[feature] webmap 对接mapboxstyle图层出图(暂未支持动态投影):
特殊处理: 1. layer id重复问题: id重复的layer添加后缀编码 (n)[参考的mapstudio] 2. 叠加图层背景色问题:经过讨论(肖睿)决定: 底图为mapboxstyle图层,使用该图层背景色;叠加mapboxstyle图层,不使用背景色(layer.type !== "background"); review by zhaoq
1 parent f39a404 commit 0f200b2

File tree

1 file changed

+134
-44
lines changed

1 file changed

+134
-44
lines changed

src/openlayers/mapping/WebMap.js

Lines changed: 134 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ const dpiConfig = {
7878
* @param {string} [options.credentialValue] - 凭证密钥对应的值,credentialKey和credentialValue必须一起使用
7979
* @param {boolean} [options.withCredentials=false] - 请求是否携带 cookie
8080
* @param {boolean} [options.excludePortalProxyUrl] - server传递过来的url是否带有代理
81+
* @param {Object} [options.serviceProxy] - iportal服务代理信息
8182
* @param {string} [options.tiandituKey] - 天地图的key
8283
* @param {function} [options.mapSetting.mapClickCallback] - 地图被点击的回调函数
8384
* @param {function} [options.mapSetting.overlays] - 地图的overlayer
@@ -99,6 +100,7 @@ export class WebMap extends Observable {
99100
this.withCredentials = options.withCredentials || false;
100101
this.target = options.target || "map";
101102
this.excludePortalProxyUrl = options.excludePortalProxyUrl || false;
103+
this.serviceProxy = options.serviceProxy || null;
102104
this.tiandituKey = options.tiandituKey;
103105
//计数叠加图层,处理过的数量(成功和失败都会计数)
104106
this.layerAdded = 0;
@@ -219,7 +221,7 @@ export class WebMap extends Observable {
219221

220222
if (mapInfo.baseLayer && mapInfo.baseLayer.layerType === 'MAPBOXSTYLE') {
221223
// 添加矢量瓦片服务作为底图
222-
that.addMVTBaseMap(mapInfo).then(() => {
224+
that.addMVTMapLayer(mapInfo, mapInfo.baseLayer, 0).then(() => {
223225
that.createView(mapInfo);
224226
if (!mapInfo.layers || mapInfo.layers.length === 0) {
225227
that.sendMapToUser(0);
@@ -503,37 +505,36 @@ export class WebMap extends Observable {
503505
this.map.addLayer(labelLayer);
504506
}
505507
}
506-
507508
/**
508509
* @private
509-
* @function ol.supermap.WebMap.prototype.addMVTBaseMap
510-
* @description 添加矢量瓦片服务底图
510+
* @function ol.supermap.WebMap.prototype.addMVTMapLayer
511+
* @description 添加地图服务mapboxstyle图层
511512
* @param {object} mapInfo - 地图信息
513+
* @param {object} layerInfo - mapboxstyle图层信息
512514
*/
513-
addMVTBaseMap(mapInfo) {
515+
addMVTMapLayer(mapInfo, layerInfo, zIndex) {
516+
layerInfo.zIndex = zIndex;
514517
// 获取地图详细信息
515-
return this.getMBStyle(mapInfo).then(() => {
518+
return this.getMBStyle(mapInfo, layerInfo).then(() => {
516519
// 创建图层
517-
let baseLayerInfo = mapInfo.baseLayer;
518-
return this.createMVTLayer(baseLayerInfo).then(layer => {
520+
return this.createMVTLayer(layerInfo).then(layer => {
519521
let layerID = Util.newGuid(8);
520-
if (baseLayerInfo.name) {
522+
if (layerInfo.name) {
521523
layer.setProperties({
522-
name: baseLayerInfo.name,
524+
name: layerInfo.name,
523525
layerID: layerID,
524526
layerType: 'VECTOR_TILE'
525527
});
526528
}
527529

528530
//否则没有ID,对不上号
529-
baseLayerInfo.layer = layer;
530-
baseLayerInfo.layerID = layerID;
531+
layerInfo.layer = layer;
532+
layerInfo.layerID = layerID;
531533

532534
this.map.addLayer(layer);
533535
});
534536
});
535537
}
536-
537538
/**
538539
* @private
539540
* @function ol.supermap.WebMap.prototype.createView
@@ -1212,7 +1213,7 @@ export class WebMap extends Observable {
12121213
getTileArray.forEach(data => {
12131214
if(data.Constraint[0].AllowedValues.Value[0].toUpperCase() === type.toUpperCase()) {
12141215
url = data.href;
1215-
}
1216+
}
12161217
})
12171218
if(!isKvp) {
12181219
//Restful格式
@@ -1278,7 +1279,7 @@ export class WebMap extends Observable {
12781279
* @param {number} dpi - 地图dpi
12791280
* @param {string} unit - 单位
12801281
* @param {number} datumAxis
1281-
* @returns {{res: Array, matrixIds: Array}}
1282+
* @returns {{res: Array, matrixIds: Array}}
12821283
*/
12831284
getReslutionsFromScales(scales, dpi, unit, datumAxis) {
12841285
unit = (unit && unit.toLowerCase()) || 'degrees';
@@ -1292,7 +1293,7 @@ export class WebMap extends Observable {
12921293
if(scale > 1.0) {
12931294
matrixIds.push(idx);
12941295
res.push(this.getResolutionFromScale(scale, dpi, unit, datumAxis));
1295-
}
1296+
}
12961297
}, this);
12971298
} else {
12981299
let tileMatrixSet = scales['TileMatrix'];
@@ -1369,8 +1370,11 @@ export class WebMap extends Observable {
13691370
let layerIndex = index + 1,
13701371
dataSource = layer.dataSource,
13711372
isSampleData = dataSource && dataSource.type === "SAMPLE_DATA" && !!dataSource.name; //SAMPLE_DATA是本地示例数据
1372-
1373-
if ((dataSource && dataSource.serverId) || layer.layerType === "MARKER" || layer.layerType === 'HOSTED_TILE' || isSampleData) {
1373+
if(layer.layerType === "MAPBOXSTYLE"){
1374+
that.addMVTMapLayer(mapInfo, layer, layerIndex);
1375+
that.layerAdded++;
1376+
that.sendMapToUser(len);
1377+
} else if ((dataSource && dataSource.serverId) || layer.layerType === "MARKER" || layer.layerType === 'HOSTED_TILE' || isSampleData) {
13741378
//数据存储到iportal上了
13751379
let dataSource = layer.dataSource,
13761380
serverId = dataSource ? dataSource.serverId : layer.serverId;
@@ -1682,7 +1686,7 @@ export class WebMap extends Observable {
16821686
layerInfo.featureType="POINT";
16831687
if(result && result.featureMetaData) {
16841688
layerInfo.featureType = result.featureMetaData.featureType.toUpperCase();
1685-
}
1689+
}
16861690
layerInfo.wsUrl = result.urls[0].url;
16871691
success();
16881692
}).catch(function () {
@@ -1833,11 +1837,11 @@ export class WebMap extends Observable {
18331837
return geojson;
18341838
}
18351839
}
1836-
1840+
18371841
/**
18381842
* @private
18391843
* @function ol.supermap.WebMap.prototype._parseGeoJsonData2Feature
1840-
* @description 将geojson的数据转换成ol.Feature
1844+
* @description 将geojson的数据转换成ol.Feature
18411845
* @param {object} metaData - 文件内容
18421846
* @returns {Array.<ol/Feature>} features
18431847
*/
@@ -1896,7 +1900,7 @@ export class WebMap extends Observable {
18961900
newFeature.properties[key] = item;
18971901
});
18981902
geojson.features.push(newFeature);
1899-
}
1903+
}
19001904
});
19011905
return geojson;
19021906
}
@@ -2130,7 +2134,7 @@ export class WebMap extends Observable {
21302134
if(dataSource.type === "USER_DATA" || dataSource.accessType==="DIRECT" ) {
21312135
that.addGeojsonFromUrl(layerInfo, null, layerIndex)
21322136
} else {
2133-
let requestUrl = that.getRequestUrl(url);
2137+
let requestUrl = that.getRequestUrl(url);
21342138
//因为itest上使用的https,iserver是http,所以要加上代理
21352139
Util.getFeatureBySQL(requestUrl, [dataSourceName], function (result) {
21362140
let features = that.parseGeoJsonData2Feature({
@@ -2380,7 +2384,7 @@ export class WebMap extends Observable {
23802384
this.map.addLayer(layer);
23812385
layer.setVisible(layerInfo.visible);
23822386
layer.setZIndex(1000);
2383-
const {visibleScale} = layerInfo;
2387+
const {visibleScale} = layerInfo;
23842388
visibleScale && this.setVisibleScales(layer, visibleScale);
23852389
return layer;
23862390
}
@@ -3833,13 +3837,15 @@ export class WebMap extends Observable {
38333837
* @description 生成图层信息
38343838
* @param {object} mapInfo - 地图信息
38353839
*/
3836-
getMBStyle(mapInfo) {
3840+
getMBStyle(mapInfo, layerInfo) {
38373841
let _this = this,
3838-
baseLayer = mapInfo.baseLayer,
3839-
dataSource = baseLayer.dataSource || {},
3842+
dataSource = layerInfo.dataSource || {},
38403843
{ url, serverId } = dataSource,
38413844
styleUrl;
38423845
styleUrl = serverId !== undefined ? `${this.server}web/datas/${serverId}/download` : url;
3846+
if (layerInfo.layerType === "MAPBOXSTYLE" && url && url.indexOf('/restjsr/') > -1) {
3847+
styleUrl = styleUrl + '/style.json'
3848+
}
38433849
return FetchRequest.get(this.getRequestUrl(styleUrl), null, {
38443850
withCredentials: this.withCredentials,
38453851
withoutFormatSuffix: true,
@@ -3851,26 +3857,72 @@ export class WebMap extends Observable {
38513857
}).then(styles => {
38523858
_this._matchStyleObject(styles);
38533859
let extent = styles.metadata.mapbounds;
3854-
baseLayer.extent = extent; // 这里把extent保存一下
3855-
3856-
baseLayer.projection = mapInfo.projection;
3857-
baseLayer.epsgCode = mapInfo.projection;
3858-
baseLayer.url = url;
3859-
baseLayer.sourceType = 'VECTOR_TILE';
3860-
baseLayer.layerType = 'VECTOR_TILE';
3861-
baseLayer.styles = styles;
3862-
baseLayer.extent = extent;
3863-
baseLayer.bounds = {
3860+
layerInfo.extent = extent; // 这里把extent保存一下
3861+
3862+
layerInfo.projection = mapInfo.projection;
3863+
layerInfo.epsgCode = mapInfo.projection;
3864+
layerInfo.url = url;
3865+
layerInfo.sourceType = 'VECTOR_TILE';
3866+
layerInfo.layerType = 'VECTOR_TILE';
3867+
layerInfo.styles = styles;
3868+
layerInfo.extent = extent;
3869+
layerInfo.bounds = {
38643870
bottom: extent[1],
38653871
left: extent[0],
38663872
leftBottom: { x: extent[0], y: extent[1] },
38673873
right: extent[2],
38683874
rightTop: { x: extent[2], y: extent[3] },
38693875
top: extent[3]
38703876
}
3877+
if (layerInfo.zIndex > 0) {
3878+
// 过滤styles 非底图mapboxstyle图层才需此处理
3879+
_this.modifyMapboxstyleLayer(mapInfo, layerInfo);
3880+
}
3881+
})
3882+
}
3883+
/**
3884+
* mapboxstyle图层:1. layer id重复问题 2.叠加图层背景色问题
3885+
* @param {web map Object} mapInfo 地图信息
3886+
* @param {Object} layerInfo 当前要添加到地图的图层
3887+
* @param {Number} zIndex 当前图层索引
3888+
*/
3889+
modifyMapboxstyleLayer(mapInfo, layerInfo) {
3890+
let that = this;
3891+
if (mapInfo.layers && mapInfo.layers.length === 0) { return; }
3892+
let curLayers = layerInfo.styles.layers;
3893+
if (!curLayers) { return; }
3894+
// 非底图,则移除"background"图层
3895+
curLayers = curLayers.filter(layer => layer.type !== "background");
3896+
layerInfo.styles.layers = curLayers;
3897+
// 处理mapboxstyle图层layer id重复的情况
3898+
let addedLayersArr = mapInfo.layers.filter(layer => layer.layerType === 'VECTOR_TILE' && layer.zIndex !== layerInfo.zIndex)
3899+
.map(addLayer => addLayer.styles && addLayer.styles.layers);
3900+
if (!addedLayersArr || addedLayersArr && addedLayersArr.length === 0) { return; }
3901+
addedLayersArr.forEach(layers => {
3902+
curLayers.forEach(curLayer => {
3903+
that.renameLayerId(layers, curLayer);
3904+
})
38713905
})
38723906
}
3907+
/**
3908+
* mapboxstyle图层 id重复的layer添加后缀编码 (n)[参考mapstudio]
3909+
* @param {mapboxgl.Layer[]} layers 已添加到地图的图层组
3910+
* @param {mapboxgl.Layer} layer 当前图层
3911+
*/
3912+
renameLayerId(layers, curLayer) {
3913+
if (layers.find((l) => l.id === curLayer.id)) {
38733914

3915+
const result = curLayer.id.match(/(.+)\((\w)\)$/);
3916+
if (result) {
3917+
curLayer.id = `${result[1]}(${+result[2] + 1})`;
3918+
} else {
3919+
curLayer.id += '(1)';
3920+
}
3921+
if (layers.find((l) => l.id === curLayer.id)) {
3922+
this.renameLayerId(layers, curLayer);
3923+
}
3924+
}
3925+
}
38743926
/**
38753927
* @private
38763928
* @function mapboxgl.supermap.WebMap.prototype._matchStyleObject
@@ -3885,8 +3937,32 @@ export class WebMap extends Observable {
38853937
if (glyphs && typeof glyphs === 'object'){
38863938
style.glyphs = Object.values(glyphs)[0];
38873939
}
3888-
}
3940+
}
38893941

3942+
/**
3943+
* 判断url是否是iportal的代理地址
3944+
* @param {*} serviceUrl
3945+
*/
3946+
isIportalProxyServiceUrl(serviceUrl) {
3947+
if (this.serviceProxy && this.serviceProxy.enable && serviceUrl) {
3948+
let proxyStr = '';
3949+
if (this.serviceProxy.proxyServerRootUrl) {
3950+
proxyStr = `${this.serviceProxy.proxyServerRootUrl}/`;
3951+
} else if (this.serviceProxy.rootUrlPostfix) {
3952+
proxyStr = `${this.serviceProxy.port}/${this.serviceProxy.rootUrlPostfix}/`;
3953+
} else if (!this.serviceProxy.rootUrlPostfix) {
3954+
proxyStr = `${this.serviceProxy.port}/`;
3955+
}
3956+
if (this.serviceProxy.port !== 80) {
3957+
return serviceUrl.indexOf(proxyStr) >= 0;
3958+
} else {
3959+
// 代理端口为80,url中不一定有端口,满足一种情况即可
3960+
return serviceUrl.indexOf(proxyStr) >= 0 || serviceUrl.indexOf(proxyStr.replace(':80', '')) >= 0;
3961+
}
3962+
} else {
3963+
return false
3964+
}
3965+
}
38903966

38913967
/**
38923968
* @private
@@ -3895,32 +3971,46 @@ export class WebMap extends Observable {
38953971
* @param {object} mapInfo - 图层信息
38963972
*/
38973973
createMVTLayer(layerInfo) {
3974+
let that = this;
38983975
let styles = layerInfo.styles;
38993976
let resolutions = this.getMVTResolutions(layerInfo.bounds);
3977+
let withCredentials = this.isIportalProxyServiceUrl(styles.sprite);
39003978
// 创建MapBoxStyle样式
39013979
let mapboxStyles = new MapboxStyles({
39023980
style: styles,
39033981
source: styles.name,
39043982
resolutions,
3905-
map: this.map
3983+
map: this.map,
3984+
withCredentials
39063985
});
39073986
return new Promise((resolve) => {
39083987
mapboxStyles.on('styleloaded', function () {
3909-
let key = Object.keys(styles.sources)[0] || mapboxStyles.name;
3910-
let url = styles.sources[key].tiles[0];
3988+
let styleUrl = layerInfo.url;
3989+
if (styleUrl.indexOf('/restjsr/') > -1) {
3990+
styleUrl = styleUrl + '/style.json'
3991+
}
3992+
let visibleScale = layerInfo.visibleScale;
3993+
let minResolution = visibleScale && that.resolutions[visibleScale.maxScale];
3994+
let maxResolution = visibleScale && that.resolutions[visibleScale.minScale];
39113995
let layer = new olLayer.VectorTile({
39123996
//设置避让参数
39133997
declutter: true,
3914-
source: new olSource.VectorTile({
3915-
url,
3998+
source: new olSource.VectorTileSuperMapRest({
3999+
style: styleUrl,
4000+
withCredentials,
39164001
projection: layerInfo.projection,
39174002
format: new MVT({
39184003
featureClass: Feature
39194004
}),
39204005
wrapX: false
39214006
}),
39224007
style: mapboxStyles.featureStyleFuntion,
3923-
visible: layerInfo.visible
4008+
visible: layerInfo.visible,
4009+
zIndex:layerInfo.zIndex,
4010+
opacity:layerInfo.opacity,
4011+
minResolution,
4012+
// The maximum resolution (exclusive) below which this layer will be visible.
4013+
maxResolution: maxResolution > 1 ? Math.ceil(maxResolution) : maxResolution * 1.1
39244014
});
39254015
resolve(layer);
39264016
})

0 commit comments

Comments
 (0)