@supermapgis/iclient-ol 11.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/control/ChangeTileVersion.js +438 -0
- package/control/Logo.js +97 -0
- package/control/ScaleLine.js +164 -0
- package/control/index.js +6 -0
- package/core/MapExtend.js +49 -0
- package/core/StyleUtils.js +1253 -0
- package/core/Util.js +500 -0
- package/core/index.js +6 -0
- package/css/ChangeTileVersion.css +347 -0
- package/css/index.js +5 -0
- package/dist/iclient-openlayers-es6.js +124963 -0
- package/dist/iclient-openlayers-es6.min.js +8 -0
- package/dist/iclient-openlayers.css +668 -0
- package/dist/iclient-openlayers.js +142946 -0
- package/dist/iclient-openlayers.min.css +8 -0
- package/dist/iclient-openlayers.min.js +8 -0
- package/index.js +9 -0
- package/mapping/BaiduMap.js +121 -0
- package/mapping/ImageSuperMapRest.js +252 -0
- package/mapping/ImageTileSuperMapRest.js +99 -0
- package/mapping/InitMap.js +150 -0
- package/mapping/SuperMapCloud.js +56 -0
- package/mapping/Tianditu.js +152 -0
- package/mapping/TileSuperMapRest.js +374 -0
- package/mapping/WebMap.js +5485 -0
- package/mapping/index.js +11 -0
- package/mapping/webmap/Util.js +176 -0
- package/mapping/webmap/config/MunicipalCenter.json +1 -0
- package/mapping/webmap/config/ProvinceCenter.json +1 -0
- package/mapping/webmap/config/SampleDataInfo.json +55 -0
- package/namespace.js +150 -0
- package/overlay/DataFlow.js +114 -0
- package/overlay/FGB.js +100 -0
- package/overlay/Graph.js +439 -0
- package/overlay/GraphMap.js +140 -0
- package/overlay/Graphic.js +588 -0
- package/overlay/HeatMap.js +450 -0
- package/overlay/Label.js +966 -0
- package/overlay/Mapv.js +149 -0
- package/overlay/Range.js +129 -0
- package/overlay/RankSymbol.js +94 -0
- package/overlay/Turf.js +299 -0
- package/overlay/Unique.js +124 -0
- package/overlay/VectorTileSuperMapRest.js +501 -0
- package/overlay/graphic/CanvasRenderer.js +177 -0
- package/overlay/graphic/CloverShape.js +133 -0
- package/overlay/graphic/Graphic.js +174 -0
- package/overlay/graphic/HitCloverShape.js +64 -0
- package/overlay/graphic/WebGLRenderer.js +356 -0
- package/overlay/graphic/index.js +9 -0
- package/overlay/index.js +21 -0
- package/overlay/mapv/MapvCanvasLayer.js +104 -0
- package/overlay/mapv/MapvLayer.js +413 -0
- package/overlay/mapv/index.js +5 -0
- package/overlay/theme/GeoFeature.js +275 -0
- package/overlay/theme/Theme.js +587 -0
- package/overlay/theme/ThemeFeature.js +46 -0
- package/overlay/theme/index.js +6 -0
- package/overlay/vectortile/DeafultCanvasStyle.js +125 -0
- package/overlay/vectortile/MapboxStyles.js +377 -0
- package/overlay/vectortile/StyleMap.js +252 -0
- package/overlay/vectortile/VectorTileStyles.js +554 -0
- package/overlay/vectortile/index.js +7 -0
- package/overlay/vectortile/olExtends.js +382 -0
- package/package.json +30 -0
- package/services/AddressMatchService.js +60 -0
- package/services/ChartService.js +97 -0
- package/services/DataFlowService.js +119 -0
- package/services/DatasetService.js +104 -0
- package/services/DatasourceService.js +76 -0
- package/services/FeatureService.js +260 -0
- package/services/FieldService.js +53 -0
- package/services/GeoprocessingService.js +157 -0
- package/services/GridCellInfosService.js +53 -0
- package/services/ImageCollectionService.js +93 -0
- package/services/ImageService.js +70 -0
- package/services/KnowledgeGraphService.js +96 -0
- package/services/LayerInfoService.js +85 -0
- package/services/MapService.js +85 -0
- package/services/MeasureService.js +77 -0
- package/services/NetworkAnalyst3DService.js +93 -0
- package/services/NetworkAnalystService.js +268 -0
- package/services/ProcessingService.js +507 -0
- package/services/QueryService.js +116 -0
- package/services/ServiceBase.js +26 -0
- package/services/SpatialAnalystService.js +466 -0
- package/services/ThemeService.js +50 -0
- package/services/TrafficTransferAnalystService.js +93 -0
- package/services/WebPrintingJobService.js +112 -0
- package/services/index.js +27 -0
|
@@ -0,0 +1,1253 @@
|
|
|
1
|
+
/* Copyright© 2000 - 2024 SuperMap Software Co.Ltd. All rights reserved.
|
|
2
|
+
* This program are made available under the terms of the Apache License, Version 2.0
|
|
3
|
+
* which accompanies this distribution and is available at http://www.apache.org/licenses/LICENSE-2.0.html.*/
|
|
4
|
+
import { Util as CommonUtil, DOTS_PER_INCH, INCHES_PER_UNIT } from '@supermapgis/iclient-common/commontypes/Util';
|
|
5
|
+
import { StringExt } from '@supermapgis/iclient-common/commontypes/BaseTypes';
|
|
6
|
+
import { StyleMap } from '../overlay/vectortile/StyleMap';
|
|
7
|
+
import { DeafultCanvasStyle } from '../overlay/vectortile/DeafultCanvasStyle';
|
|
8
|
+
import { Util } from '../core/Util';
|
|
9
|
+
import Canvg from 'canvg';
|
|
10
|
+
import Style from 'ol/style/Style';
|
|
11
|
+
import Icon from 'ol/style/Icon';
|
|
12
|
+
import CircleStyle from 'ol/style/Circle';
|
|
13
|
+
import FillStyle from 'ol/style/Fill';
|
|
14
|
+
import StrokeStyle from 'ol/style/Stroke';
|
|
15
|
+
import Text from 'ol/style/Text';
|
|
16
|
+
|
|
17
|
+
var padding = 8, doublePadding = padding * 2;
|
|
18
|
+
const ZERO = 0.0000001;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @class StyleUtils
|
|
22
|
+
* @classdesc 样式工具类。
|
|
23
|
+
* @private
|
|
24
|
+
*/
|
|
25
|
+
export class StyleUtils {
|
|
26
|
+
/**
|
|
27
|
+
* @function StyleUtils.getValidStyleFromLayerInfo
|
|
28
|
+
* @description 通过图层信息获取有效的样式。
|
|
29
|
+
* @param {Object} layerInfo - 图层信息。
|
|
30
|
+
* @param {ol.Feature} feature - 要素。
|
|
31
|
+
* @param {string} url - 图层数据地址。
|
|
32
|
+
* @returns {ol.style.Style} 返回图层样式。
|
|
33
|
+
*/
|
|
34
|
+
static getValidStyleFromLayerInfo(layerInfo, feature, url) {
|
|
35
|
+
var type = feature.getGeometry().getType().toUpperCase(),
|
|
36
|
+
shader = layerInfo.layerStyle,
|
|
37
|
+
style = this.getDefaultStyle(type);
|
|
38
|
+
if ((type === "POINT" || type === 'MULTIPOINT') && !feature.getProperties().textStyle && layerInfo.type !== 'LABEL' && !feature.getProperties().TEXT_FEATURE_CONTENT) {
|
|
39
|
+
if (shader) {
|
|
40
|
+
var symbolParameters = {
|
|
41
|
+
"transparent": true,
|
|
42
|
+
"resourceType": "SYMBOLMARKER",
|
|
43
|
+
"picWidth": Math.ceil(shader.markerSize * DOTS_PER_INCH * INCHES_PER_UNIT["mm"]) || 13,
|
|
44
|
+
"picHeight": Math.ceil(shader.markerSize * DOTS_PER_INCH * INCHES_PER_UNIT["mm"]) || 13,
|
|
45
|
+
"style": JSON.stringify(shader)
|
|
46
|
+
};
|
|
47
|
+
var imageUrl = CommonUtil.urlAppend(url + "/symbol.png", CommonUtil.getParameterString(symbolParameters));
|
|
48
|
+
style.pointFile = imageUrl;
|
|
49
|
+
return new Style({
|
|
50
|
+
image: new Icon({
|
|
51
|
+
src: style.pointFile
|
|
52
|
+
})
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return this.toOLPointStyle(style);
|
|
56
|
+
} else if ((type === "POINT" || type === 'MULTIPOINT') && (feature.getProperties().textStyle || layerInfo.type === 'LABEL' || feature.getProperties().TEXT_STYLE_INFO)) {
|
|
57
|
+
style = this.getDefaultStyle('TEXT');
|
|
58
|
+
if (feature.getProperties().textStyle) {
|
|
59
|
+
shader = feature.getProperties().textStyle;
|
|
60
|
+
}
|
|
61
|
+
if (feature.getProperties().TEXT_STYLE_INFO) {
|
|
62
|
+
shader = JSON.parse(feature.getProperties().TEXT_STYLE_INFO).textStyle;
|
|
63
|
+
}
|
|
64
|
+
if (shader && shader !== "{}") {
|
|
65
|
+
var fontStr = "";
|
|
66
|
+
//设置文本是否倾斜
|
|
67
|
+
style.fontStyle = shader.italic ? "italic" : "normal";
|
|
68
|
+
//设置文本是否使用粗体
|
|
69
|
+
style.fontWeight = shader.bold ? shader.fontWeight : "normal";
|
|
70
|
+
//设置文本的尺寸(对应fontHeight属性)和行高,行高iserver不支持,默认5像素
|
|
71
|
+
//固定大小的时候单位是毫米
|
|
72
|
+
var text_h = shader.fontHeight * DOTS_PER_INCH * INCHES_PER_UNIT["mm"] * 0.85; //毫米转像素,服务端的字体貌似要稍微小一点
|
|
73
|
+
style.fontSize = text_h + "px";
|
|
74
|
+
|
|
75
|
+
//设置文本字体类型
|
|
76
|
+
//在桌面字体钱加@时为了解决对联那种形式,但是在canvas不支持,并且添加了@会导致
|
|
77
|
+
//字体大小被固定,这里需要去掉
|
|
78
|
+
if (shader.fontName.indexOf("@")) {
|
|
79
|
+
fontStr = shader.fontName.replace(/@/g, "");
|
|
80
|
+
} else {
|
|
81
|
+
fontStr = shader.fontName
|
|
82
|
+
}
|
|
83
|
+
style.fontFamily = fontStr;
|
|
84
|
+
style.textHeight = text_h;
|
|
85
|
+
|
|
86
|
+
//设置对齐方式
|
|
87
|
+
var alignStr = shader.align.replace(/TOP|MIDDLE|BASELINE|BOTTOM/, "");
|
|
88
|
+
style.textAlign = alignStr.toLowerCase();
|
|
89
|
+
var baselineStr = shader.align.replace(/LEFT|RIGHT|CENTER/, "");
|
|
90
|
+
if (baselineStr === "BASELINE") {
|
|
91
|
+
baselineStr = "alphabetic";
|
|
92
|
+
}
|
|
93
|
+
style.textBaseline = baselineStr.toLowerCase();
|
|
94
|
+
|
|
95
|
+
/*//首先判定是否需要绘制阴影,如果需要绘制,阴影应该在最下面
|
|
96
|
+
if(shader.shadow)
|
|
97
|
+
{
|
|
98
|
+
|
|
99
|
+
//桌面里面的阴影没有做模糊处理,这里统一设置为0,
|
|
100
|
+
style.shadowBlur=0;
|
|
101
|
+
//和桌面统一,往右下角偏移阴影,默认3像素
|
|
102
|
+
style.shadowOffsetX=3;
|
|
103
|
+
style.shadowOffsetY=3;
|
|
104
|
+
//颜色取一个灰色,调成半透明
|
|
105
|
+
style.shadowColor="rgba(50,50,50,0.5)";
|
|
106
|
+
}else{
|
|
107
|
+
style.shadowOffsetX=0;
|
|
108
|
+
style.shadowOffsetY=0;
|
|
109
|
+
}*/
|
|
110
|
+
style.haloRadius = shader.outline ? shader.outlineWidth : 0;
|
|
111
|
+
style.backColor = "rgba(" + shader.backColor.red + "," + shader.backColor.green + "," + shader.backColor.blue + ",1)";
|
|
112
|
+
style.foreColor = "rgba(" + shader.foreColor.red + "," + shader.foreColor.green + "," + shader.foreColor.blue + ",1)";
|
|
113
|
+
style.rotation = shader.rotation;
|
|
114
|
+
}
|
|
115
|
+
var text;
|
|
116
|
+
if (feature.getProperties().textStyle && feature.getProperties().texts) {
|
|
117
|
+
text = feature.getProperties().texts[0];
|
|
118
|
+
}
|
|
119
|
+
if (layerInfo.type === 'LABEL') {
|
|
120
|
+
var textField = layerInfo.textField;
|
|
121
|
+
if (textField && textField.indexOf('.')) {
|
|
122
|
+
var arr = textField.split('.');
|
|
123
|
+
textField = arr && arr.length > 0 && arr[arr.length - 1];
|
|
124
|
+
}
|
|
125
|
+
text = feature.getProperties().attributes ? feature.getProperties().attributes[textField] : feature.getProperties()[textField];
|
|
126
|
+
}
|
|
127
|
+
if (feature.getProperties().TEXT_FEATURE_CONTENT) {
|
|
128
|
+
text = feature.getProperties().TEXT_FEATURE_CONTENT;
|
|
129
|
+
}
|
|
130
|
+
if (!text) {
|
|
131
|
+
return this.toOLPointStyle(this.getDefaultStyle('POINT'));
|
|
132
|
+
}
|
|
133
|
+
return this.toOLTextStyle(style, text);
|
|
134
|
+
} else if (shader) {
|
|
135
|
+
//目前只实现桌面系统默认的几种symbolID,非系统默认的面用颜色填充替代,线则用实线来替代
|
|
136
|
+
var fillSymbolID = shader["fillSymbolID"] > 7 ? 0 : shader["fillSymbolID"];
|
|
137
|
+
var lineSymbolID = shader["lineSymbolID"] > 5 ? 0 : shader["lineSymbolID"];
|
|
138
|
+
for (var attr in shader) {
|
|
139
|
+
var obj = StyleMap.ServerStyleMap[attr];
|
|
140
|
+
var canvasStyle = obj.canvasStyle;
|
|
141
|
+
if (canvasStyle && canvasStyle != "") {
|
|
142
|
+
var value;
|
|
143
|
+
switch (obj.type) {
|
|
144
|
+
case "number":
|
|
145
|
+
value = shader[attr];
|
|
146
|
+
if (obj.unit) {
|
|
147
|
+
//将单位转换为像素单位
|
|
148
|
+
value = value * DOTS_PER_INCH * INCHES_PER_UNIT[obj.unit] * 2.5;
|
|
149
|
+
}
|
|
150
|
+
style[canvasStyle] = value;
|
|
151
|
+
break;
|
|
152
|
+
case "color":
|
|
153
|
+
var color = shader[attr];
|
|
154
|
+
var backColor = shader["fillBackColor"];
|
|
155
|
+
var alpha = 1;
|
|
156
|
+
if (canvasStyle === "fillStyle") {
|
|
157
|
+
if (fillSymbolID === 0 || fillSymbolID === 1) {
|
|
158
|
+
//当fillSymbolID为0时,用颜色填充,为1是无填充,即为透明填充,alpha通道为0
|
|
159
|
+
alpha = 1 - fillSymbolID;
|
|
160
|
+
value = "rgba(" + color.red + "," + color.green + "," + color.blue + "," + alpha + ")";
|
|
161
|
+
} else {
|
|
162
|
+
//当fillSymbolID为2~7时,用的纹理填充,但要按照前景色修改其颜色
|
|
163
|
+
try {
|
|
164
|
+
var tempCvs = document.createElement("canvas");
|
|
165
|
+
tempCvs.height = 8;
|
|
166
|
+
tempCvs.width = 8;
|
|
167
|
+
var tempCtx = tempCvs.getContext("2d");
|
|
168
|
+
var image = new Image();
|
|
169
|
+
if (this.layer && this.layer.fillImages) {
|
|
170
|
+
tempCtx.drawImage(this.layer.fillImages["System " + fillSymbolID], 0, 0);
|
|
171
|
+
}
|
|
172
|
+
var imageData = tempCtx.getImageData(0, 0, tempCvs.width, tempCvs.height);
|
|
173
|
+
var pix = imageData.data;
|
|
174
|
+
for (var i = 0, len = pix.length; i < len; i += 4) {
|
|
175
|
+
var r = pix[i], g = pix[i + 1], b = pix[i + 2];
|
|
176
|
+
//将符号图片中的灰色或者黑色的部分替换为前景色,其余为后景色
|
|
177
|
+
if (r < 225 && g < 225 && b < 225) {
|
|
178
|
+
pix[i] = color.red;
|
|
179
|
+
pix[i + 1] = color.green;
|
|
180
|
+
pix[i + 2] = color.blue;
|
|
181
|
+
} else if (backColor) {
|
|
182
|
+
pix[i] = backColor.red;
|
|
183
|
+
pix[i + 1] = backColor.green;
|
|
184
|
+
pix[i + 2] = backColor.blue;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
tempCtx.putImageData(imageData, 0, 0);
|
|
188
|
+
image.src = tempCvs.toDataURL();
|
|
189
|
+
|
|
190
|
+
if (this.context) {
|
|
191
|
+
value = this.context.createPattern(image, "repeat");
|
|
192
|
+
}
|
|
193
|
+
} catch (e) {
|
|
194
|
+
throw Error(e.message);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
} else if (canvasStyle === "strokeStyle") {
|
|
198
|
+
if (lineSymbolID === 0 || lineSymbolID === 5) {
|
|
199
|
+
//对于lineSymbolID为0时,线为实线,为lineSymbolID为5时,为无线模式,即线为透明,即alpha通道为0
|
|
200
|
+
alpha = lineSymbolID === 0 ? 1 : 0;
|
|
201
|
+
} else {
|
|
202
|
+
//以下几种linePattern分别模拟了桌面的SymbolID为1~4几种符号的linePattern
|
|
203
|
+
var linePattern = [1, 0];
|
|
204
|
+
switch (lineSymbolID) {
|
|
205
|
+
case 1:
|
|
206
|
+
linePattern = [9.7, 3.7];
|
|
207
|
+
break;
|
|
208
|
+
case 2:
|
|
209
|
+
linePattern = [3.7, 3.7];
|
|
210
|
+
break;
|
|
211
|
+
case 3:
|
|
212
|
+
linePattern = [9.7, 3.7, 2.3, 3.7];
|
|
213
|
+
break;
|
|
214
|
+
case 4:
|
|
215
|
+
linePattern = [9.7, 3.7, 2.3, 3.7, 2.3, 3.7];
|
|
216
|
+
break;
|
|
217
|
+
default:
|
|
218
|
+
break
|
|
219
|
+
}
|
|
220
|
+
style.lineDasharray = linePattern;
|
|
221
|
+
}
|
|
222
|
+
value = "rgba(" + color.red + "," + color.green + "," + color.blue + "," + alpha + ")";
|
|
223
|
+
}
|
|
224
|
+
style[canvasStyle] = value;
|
|
225
|
+
break;
|
|
226
|
+
default:
|
|
227
|
+
break;
|
|
228
|
+
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (type === 'LINESTRING' || type === 'MULTILINESTRING') {
|
|
234
|
+
return this.toOLLineStyle(style);
|
|
235
|
+
}
|
|
236
|
+
if (type === 'POLYGON' || type === 'MULTIPOLYGON') {
|
|
237
|
+
return this.toOLPolygonStyle(style);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* @function StyleUtils.getStyleFromCarto
|
|
243
|
+
* @description 从 Carto 中获取有效的样式。
|
|
244
|
+
* @param {number} zoom -缩放级别。
|
|
245
|
+
* @param {number} scale - 比例尺。
|
|
246
|
+
* @param {Array.<Object>} shader - 渲染器对象数组。
|
|
247
|
+
* @param {Object} feature - 要素。
|
|
248
|
+
* @param {string} fromServer - 服务源。
|
|
249
|
+
* @param {string} url - 地址。
|
|
250
|
+
*/
|
|
251
|
+
static getStyleFromCarto(zoom, scale, shader, feature, fromServer, url) {
|
|
252
|
+
var type = feature.getGeometry().getType().toUpperCase(),
|
|
253
|
+
attributes = {},
|
|
254
|
+
style = this.getDefaultStyle(type);
|
|
255
|
+
attributes.FEATUREID = feature.getProperties().id;
|
|
256
|
+
attributes.SCALE = scale;
|
|
257
|
+
var cartoStyleType = feature.getProperties().type === "TEXT" ? "TEXT" : type;
|
|
258
|
+
var cartoStyleMap = StyleMap.CartoStyleMap[cartoStyleType];
|
|
259
|
+
var fontSize, fontName;
|
|
260
|
+
if (shader) {
|
|
261
|
+
for (var i = 0, len = shader.length; i < len; i++) {
|
|
262
|
+
var _shader = shader[i];
|
|
263
|
+
var prop = cartoStyleMap[_shader.property];
|
|
264
|
+
var value = _shader.getValue(attributes, zoom, true);
|
|
265
|
+
if ((value !== null) && prop) {
|
|
266
|
+
if (prop === "fontSize") {
|
|
267
|
+
if (fromServer) {
|
|
268
|
+
value *= 0.8;
|
|
269
|
+
}
|
|
270
|
+
//斜杠后面为行间距,默认为0.5倍行间距
|
|
271
|
+
fontSize = value + "px";
|
|
272
|
+
style.fontSize = fontSize;
|
|
273
|
+
} else if (prop === "fontName") {
|
|
274
|
+
fontName = value;
|
|
275
|
+
style.fontName = fontName;
|
|
276
|
+
} else {
|
|
277
|
+
if (prop === "globalCompositeOperation") {
|
|
278
|
+
value = StyleMap.CartoCompOpMap[value];
|
|
279
|
+
if (!value) {
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
} else if (fromServer && prop === 'pointFile') {
|
|
283
|
+
value = url + '/tileFeature/symbols/' + value.replace(/(___)/gi, '@');
|
|
284
|
+
value = value.replace(/(__0__0__)/gi, '__8__8__');
|
|
285
|
+
}
|
|
286
|
+
if (prop === 'lineWidth' && value < 1) {
|
|
287
|
+
value = Math.ceil(value);
|
|
288
|
+
}
|
|
289
|
+
style[prop] = value;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (feature.getProperties().type === 'TEXT') {
|
|
295
|
+
var text;
|
|
296
|
+
if (feature.getProperties().texts) {
|
|
297
|
+
text = feature.getProperties().texts[0];
|
|
298
|
+
}
|
|
299
|
+
if (text == null && style.textName) {
|
|
300
|
+
var textName = style.textName.substring(1, style.textName.length - 1);
|
|
301
|
+
text = feature.getProperties().attributes ? feature.getProperties().attributes[textName] : feature.getProperties()[textName];
|
|
302
|
+
if (text != null) {
|
|
303
|
+
var texts = feature.getProperties().texts || [];
|
|
304
|
+
texts.push(text);
|
|
305
|
+
feature.setProperties({ texts: texts });
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return this.toOLTextStyle(style, text)
|
|
309
|
+
}
|
|
310
|
+
if (type === 'POINT' || type === 'MULTIPOINT') {
|
|
311
|
+
return this.toOLPointStyle(style);
|
|
312
|
+
}
|
|
313
|
+
if (type === 'LINESTRING' || type === 'MULTILINESTRING') {
|
|
314
|
+
return this.toOLLineStyle(style);
|
|
315
|
+
}
|
|
316
|
+
if (type === 'POLYGON' || type === 'MULTIPOLYGON') {
|
|
317
|
+
return this.toOLPolygonStyle(style);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* @function StyleUtils.toOLPointStyle
|
|
323
|
+
* @description 点样式。
|
|
324
|
+
* @param {Object} style - 样式参数。
|
|
325
|
+
* @returns {ol.style.Style} 获取点样式。
|
|
326
|
+
*/
|
|
327
|
+
static toOLPointStyle(style) {
|
|
328
|
+
if (style.pointFile !== '') {
|
|
329
|
+
return new Style({
|
|
330
|
+
image: new Icon({
|
|
331
|
+
src: style.pointFile
|
|
332
|
+
})
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
return new Style({
|
|
336
|
+
image: new CircleStyle({
|
|
337
|
+
radius: style.pointRadius,
|
|
338
|
+
fill: new FillStyle({
|
|
339
|
+
color: style.fillStyle
|
|
340
|
+
}),
|
|
341
|
+
stroke: new StrokeStyle({
|
|
342
|
+
color: style.pointHaloColor,
|
|
343
|
+
width: style.pointHaloRadius
|
|
344
|
+
})
|
|
345
|
+
})
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* @function StyleUtils.toOLLineStyle
|
|
351
|
+
* @description 线样式。
|
|
352
|
+
* @param {Object} style - 样式参数。
|
|
353
|
+
* @returns {ol.style.Style} 获取线的样式。
|
|
354
|
+
*/
|
|
355
|
+
static toOLLineStyle(style) {
|
|
356
|
+
return new Style({
|
|
357
|
+
stroke: new StrokeStyle({
|
|
358
|
+
color: style.strokeStyle,
|
|
359
|
+
width: style.lineWidth,
|
|
360
|
+
lineCap: style.lineCap,
|
|
361
|
+
lineDash: style.lineDasharray,
|
|
362
|
+
lineDashOffset: style.lineDashOffset,
|
|
363
|
+
lineJoin: style.lineJoin,
|
|
364
|
+
miterLimit: style.miterLimit
|
|
365
|
+
})
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* @function StyleUtils.toOLPolygonStyle
|
|
371
|
+
* @description 面样式。
|
|
372
|
+
* @param {Object} style - 样式参数。
|
|
373
|
+
* @returns {ol.style.Style} 获取面的样式。
|
|
374
|
+
*/
|
|
375
|
+
static toOLPolygonStyle(style) {
|
|
376
|
+
var fill = new FillStyle({
|
|
377
|
+
color: style.fillStyle
|
|
378
|
+
});
|
|
379
|
+
var stroke = new StrokeStyle({
|
|
380
|
+
color: style.strokeStyle,
|
|
381
|
+
width: style.lineWidth,
|
|
382
|
+
lineCap: style.lineCap,
|
|
383
|
+
lineDash: style.lineDasharray,
|
|
384
|
+
lineDashOffset: style.lineDashOffset,
|
|
385
|
+
lineJoin: style.lineJoin,
|
|
386
|
+
miterLimit: style.miterLimit
|
|
387
|
+
});
|
|
388
|
+
return new Style({
|
|
389
|
+
fill: fill,
|
|
390
|
+
stroke: stroke
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* @function StyleUtils.toOLTextStyle
|
|
396
|
+
* @description 文本样式。
|
|
397
|
+
* @param {Object} style - 样式对象。
|
|
398
|
+
* @param {string} text - 文本参数。
|
|
399
|
+
* @returns {ol.style.Style} 获取的文本样式。
|
|
400
|
+
*/
|
|
401
|
+
static toOLTextStyle(style, text) {
|
|
402
|
+
return new Style({
|
|
403
|
+
text: new Text({
|
|
404
|
+
font: (style.fontStyle || '') + ' ' + (style.fontWeight || '') + ' ' + (style.fontSize || '') + ' ' + style.fontFamily,
|
|
405
|
+
text: text,
|
|
406
|
+
textAlign: style.textAlign,
|
|
407
|
+
textBaseline: style.textBaseline,
|
|
408
|
+
fill: new FillStyle({
|
|
409
|
+
color: style.foreColor
|
|
410
|
+
}),
|
|
411
|
+
stroke: new StrokeStyle({
|
|
412
|
+
color: style.backColor
|
|
413
|
+
}),
|
|
414
|
+
offsetX: style.offsetX,
|
|
415
|
+
offsetY: style.offsetY
|
|
416
|
+
})
|
|
417
|
+
})
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* @function StyleUtils.dashStyle
|
|
422
|
+
* @description 符号样式。
|
|
423
|
+
* @param {Object} style - 样式参数。
|
|
424
|
+
* @param {number} widthFactor - 宽度系数。
|
|
425
|
+
*/
|
|
426
|
+
static dashStyle(style, widthFactor) {
|
|
427
|
+
if (!style) {
|
|
428
|
+
return [];
|
|
429
|
+
}
|
|
430
|
+
var w = style.strokeWidth * widthFactor;
|
|
431
|
+
var str = style.strokeDashstyle || style.lineDash;
|
|
432
|
+
switch (str) {
|
|
433
|
+
case 'solid':
|
|
434
|
+
return [0];
|
|
435
|
+
case 'dot':
|
|
436
|
+
return [1, 4 * w];
|
|
437
|
+
case 'dash':
|
|
438
|
+
return [4 * w, 4 * w];
|
|
439
|
+
case 'dashdot':
|
|
440
|
+
return [4 * w, 4 * w, 1, 4 * w];
|
|
441
|
+
case 'longdash':
|
|
442
|
+
return [8 * w, 4 * w];
|
|
443
|
+
case 'longdashdot':
|
|
444
|
+
return [8 * w, 4 * w, 1, 4 * w];
|
|
445
|
+
default:
|
|
446
|
+
if (!str) {
|
|
447
|
+
return [];
|
|
448
|
+
}
|
|
449
|
+
if (CommonUtil.isArray(str)) {
|
|
450
|
+
return str;
|
|
451
|
+
}
|
|
452
|
+
str = StringExt.trim(str).replace(/\s+/g, ",");
|
|
453
|
+
return str.replace(/\[|\]/gi, "").split(",");
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* @function StyleUtils.getStyleFromiPortalMarker
|
|
459
|
+
* @description 从 SuperMap iPortal 标记获取样式。
|
|
460
|
+
* @param {Object} icon - 图标参数。
|
|
461
|
+
*/
|
|
462
|
+
static getStyleFromiPortalMarker(icon) {
|
|
463
|
+
if (icon.indexOf("./") == 0) {
|
|
464
|
+
return null;
|
|
465
|
+
}
|
|
466
|
+
//兼容iportal示例的问题
|
|
467
|
+
// if (icon.indexOf("http://support.supermap.com.cn:8092/static/portal") == 0) {
|
|
468
|
+
// icon = icon.replace("http://support.supermap.com.cn:8092/static/portal", "http://support.supermap.com.cn:8092/apps/viewer/static");
|
|
469
|
+
// }
|
|
470
|
+
return new Style({
|
|
471
|
+
image: new Icon({
|
|
472
|
+
src: icon,
|
|
473
|
+
opacity: 1,
|
|
474
|
+
size: [48, 43],
|
|
475
|
+
anchor: [0.5, 1]
|
|
476
|
+
})
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* @function StyleUtils.getStyleFromiPortalStyle
|
|
482
|
+
* @description 从 SuperMap iPortal 标记获取样式。
|
|
483
|
+
* @param {Object} iPortalStyle - SuperMap iPortal 样式。
|
|
484
|
+
* @param {string} type - 样式类型。
|
|
485
|
+
* @param {Object} fStyle - 要素样式。
|
|
486
|
+
*/
|
|
487
|
+
static getStyleFromiPortalStyle(iPortalStyle, type, fStyle) {
|
|
488
|
+
var featureStyle = fStyle ? JSON.parse(fStyle) : null;
|
|
489
|
+
var me = this;
|
|
490
|
+
if (type === 'Point' || type === 'MultiPoint') {
|
|
491
|
+
var pointStyle = featureStyle || iPortalStyle.pointStyle;
|
|
492
|
+
if (pointStyle.externalGraphic) {
|
|
493
|
+
if (pointStyle.externalGraphic.indexOf("./") == 0) {
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
//兼容iportal示例的问题
|
|
497
|
+
// if (pointStyle.externalGraphic.indexOf("http://support.supermap.com.cn:8092/static/portal") == 0) {
|
|
498
|
+
// pointStyle.externalGraphic = pointStyle.externalGraphic.replace("http://support.supermap.com.cn:8092/static/portal", "http://support.supermap.com.cn:8092/apps/viewer/static");
|
|
499
|
+
// }
|
|
500
|
+
return new Style({
|
|
501
|
+
image: new Icon({
|
|
502
|
+
src: pointStyle.externalGraphic,
|
|
503
|
+
opacity: pointStyle.graphicOpacity,
|
|
504
|
+
size: [pointStyle.graphicWidth, pointStyle.graphicHeight]
|
|
505
|
+
//anchor: [-pointStyle.graphicXOffset / pointStyle.graphicWidth, -pointStyle.graphicYOffset / pointStyle.graphicHeight]
|
|
506
|
+
})
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
return new Style({
|
|
510
|
+
image: new CircleStyle({
|
|
511
|
+
fill: new FillStyle({
|
|
512
|
+
color: me.hexToRgba(pointStyle.fillColor, pointStyle.fillOpacity)
|
|
513
|
+
}),
|
|
514
|
+
stroke: new StrokeStyle({
|
|
515
|
+
color: me.hexToRgba(pointStyle.strokeColor, pointStyle.strokeOpacity),
|
|
516
|
+
lineCap: pointStyle.strokeLineCap,
|
|
517
|
+
lineDash: this.dashStyle(pointStyle, 1),
|
|
518
|
+
width: pointStyle.strokeWidth
|
|
519
|
+
}),
|
|
520
|
+
radius: pointStyle.pointRadius
|
|
521
|
+
})
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
if (type === 'LineString' || type === 'MultiLineString' || type === 'Box') {
|
|
525
|
+
var lineStyle = featureStyle || iPortalStyle.lineStyle;
|
|
526
|
+
return new Style({
|
|
527
|
+
stroke: new StrokeStyle({
|
|
528
|
+
color: me.hexToRgba(lineStyle.strokeColor, lineStyle.strokeOpacity),
|
|
529
|
+
lineCap: lineStyle.strokeLineCap,
|
|
530
|
+
lineDash: this.dashStyle(lineStyle, 1),
|
|
531
|
+
width: lineStyle.strokeWidth
|
|
532
|
+
})
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
if (type === 'Polygon' || type === 'MultiPolygon') {
|
|
536
|
+
var polygonStyle = featureStyle || iPortalStyle.polygonStyle;
|
|
537
|
+
return new Style({
|
|
538
|
+
fill: new FillStyle({
|
|
539
|
+
color: me.hexToRgba(polygonStyle.fillColor, polygonStyle.fillOpacity)
|
|
540
|
+
}),
|
|
541
|
+
stroke: new StrokeStyle({
|
|
542
|
+
color: me.hexToRgba(polygonStyle.strokeColor, polygonStyle.strokeOpacity),
|
|
543
|
+
lineCap: polygonStyle.strokeLineCap,
|
|
544
|
+
lineDash: this.dashStyle(polygonStyle, 1),
|
|
545
|
+
width: polygonStyle.strokeWidth
|
|
546
|
+
})
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* @function StyleUtils.hexToRgba
|
|
553
|
+
* @description 十六进制转 RGBA 格式。
|
|
554
|
+
* @param {Object} hex - 十六进制格式参数。
|
|
555
|
+
* @param {number} opacity -Alpha 参数。
|
|
556
|
+
* @returns {string} 生成的 RGBA 格式。
|
|
557
|
+
*/
|
|
558
|
+
static hexToRgba(hex, opacity) {
|
|
559
|
+
var color = [], rgba = [];
|
|
560
|
+
hex = hex.replace(/#/, "");
|
|
561
|
+
if (hex.length == 3) {
|
|
562
|
+
var tmp = [];
|
|
563
|
+
for (let i = 0; i < 3; i++) {
|
|
564
|
+
tmp.push(hex.charAt(i) + hex.charAt(i));
|
|
565
|
+
}
|
|
566
|
+
hex = tmp.join("");
|
|
567
|
+
}
|
|
568
|
+
for (let i = 0; i < 6; i += 2) {
|
|
569
|
+
color[i] = "0x" + hex.substr(i, 2);
|
|
570
|
+
rgba.push(parseInt(Number(color[i])));
|
|
571
|
+
}
|
|
572
|
+
rgba.push(opacity);
|
|
573
|
+
return "rgba(" + rgba.join(",") + ")";
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* @function StyleUtils.getDefaultStyle
|
|
578
|
+
* @description 获取默认风格
|
|
579
|
+
* @param {string} type - 类型参数。
|
|
580
|
+
* @returns {string}
|
|
581
|
+
*/
|
|
582
|
+
static getDefaultStyle(type) {
|
|
583
|
+
var style = {};
|
|
584
|
+
var canvasStyle = DeafultCanvasStyle[type];
|
|
585
|
+
for (var prop in canvasStyle) {
|
|
586
|
+
var val = canvasStyle[prop];
|
|
587
|
+
style[prop] = val;
|
|
588
|
+
}
|
|
589
|
+
return style;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* @function StyleUtils.getDefaultStyle
|
|
594
|
+
* @description 将样式对象转换成openlayer要求的ol.style
|
|
595
|
+
* @param {string} style - 样式对象
|
|
596
|
+
* @param {string} type - feature的类型
|
|
597
|
+
* @returns {Promise<ol.style.Style>}
|
|
598
|
+
*/
|
|
599
|
+
static async toOpenLayersStyle(style, type) {
|
|
600
|
+
style = style || this.getDefaultStyle();
|
|
601
|
+
let olStyle = new Style();
|
|
602
|
+
let newImage, newFill, newStroke;
|
|
603
|
+
let {
|
|
604
|
+
fillColor,
|
|
605
|
+
fillOpacity,
|
|
606
|
+
strokeColor,
|
|
607
|
+
strokeWidth,
|
|
608
|
+
strokeOpacity,
|
|
609
|
+
radius,
|
|
610
|
+
lineCap,
|
|
611
|
+
src,
|
|
612
|
+
scale,
|
|
613
|
+
offsetX,
|
|
614
|
+
offsetY,
|
|
615
|
+
//size,
|
|
616
|
+
//imgSize,
|
|
617
|
+
anchor
|
|
618
|
+
} = style;
|
|
619
|
+
let fillColorArray = this.hexToRgb(fillColor);
|
|
620
|
+
if (fillColorArray) {
|
|
621
|
+
fillColorArray.push(fillOpacity);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
let strokeColorArray = this.hexToRgb(strokeColor);
|
|
625
|
+
if (strokeColorArray) {
|
|
626
|
+
strokeColorArray.push(strokeOpacity);
|
|
627
|
+
}
|
|
628
|
+
if (type === "POINT") {
|
|
629
|
+
if (src) {
|
|
630
|
+
if (/.+(\.svg$)/.test(src)) {
|
|
631
|
+
if (!this.svgDiv) {
|
|
632
|
+
this.svgDiv = document.createElement('div');
|
|
633
|
+
document.body.appendChild(this.svgDiv);
|
|
634
|
+
}
|
|
635
|
+
await this.getCanvasFromSVG(src, this.svgDiv, (canvas) => {
|
|
636
|
+
newImage = new Icon({
|
|
637
|
+
img: canvas,
|
|
638
|
+
scale: radius / canvas.width,
|
|
639
|
+
imgSize: [canvas.width, canvas.height],
|
|
640
|
+
anchor: [0.5, 0.5]
|
|
641
|
+
})
|
|
642
|
+
})
|
|
643
|
+
} else {
|
|
644
|
+
newImage = new Icon({
|
|
645
|
+
src: src,
|
|
646
|
+
scale: scale,
|
|
647
|
+
anchor: anchor
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
} else {
|
|
651
|
+
newImage = new CircleStyle({
|
|
652
|
+
radius,
|
|
653
|
+
fill: new FillStyle({
|
|
654
|
+
color: fillColorArray
|
|
655
|
+
}),
|
|
656
|
+
stroke: new StrokeStyle({
|
|
657
|
+
width: strokeWidth || ZERO,
|
|
658
|
+
color: strokeColorArray
|
|
659
|
+
}),
|
|
660
|
+
displacement: this.getCircleDisplacement(radius, offsetX, offsetY)
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
olStyle.setImage(newImage);
|
|
664
|
+
} else if (type === "LINE" || type === "LINESTRING" || type === 'MULTILINESTRING' || type === 'LINEARRING') {
|
|
665
|
+
newStroke = new StrokeStyle({
|
|
666
|
+
width: strokeWidth || ZERO,
|
|
667
|
+
color: strokeColorArray,
|
|
668
|
+
lineCap: lineCap || 'round',
|
|
669
|
+
lineDash: this.dashStyle(style, 1)
|
|
670
|
+
});
|
|
671
|
+
olStyle.setStroke(newStroke);
|
|
672
|
+
} else if (type === 'POLYGON' ||
|
|
673
|
+
type === 'MULTIPOLYGON' || type === 'REGION') {
|
|
674
|
+
newFill = new FillStyle({
|
|
675
|
+
color: fillColorArray
|
|
676
|
+
});
|
|
677
|
+
newStroke = new StrokeStyle({
|
|
678
|
+
width: strokeWidth || ZERO,
|
|
679
|
+
color: strokeColorArray,
|
|
680
|
+
lineCap: lineCap || 'round',
|
|
681
|
+
lineDash: this.dashStyle(style, 1)
|
|
682
|
+
});
|
|
683
|
+
olStyle.setFill(newFill);
|
|
684
|
+
olStyle.setStroke(newStroke);
|
|
685
|
+
} else {
|
|
686
|
+
let result = this.getCanvas(style);
|
|
687
|
+
newImage = new Icon({
|
|
688
|
+
img: result.canvas,
|
|
689
|
+
imgSize: [result.width, result.height],
|
|
690
|
+
scale: 1,
|
|
691
|
+
anchor: [0.5, 0.5]
|
|
692
|
+
});
|
|
693
|
+
olStyle.setImage(newImage);
|
|
694
|
+
}
|
|
695
|
+
return olStyle;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* @function StyleUtils.getIconAnchor
|
|
700
|
+
* @description 获取图标的锚点
|
|
701
|
+
* @param {number} offsetX - X方向偏移分数
|
|
702
|
+
* @param {number} offsetY - Y方向偏移分数
|
|
703
|
+
* @returns {Array.<number>}
|
|
704
|
+
*/
|
|
705
|
+
static getIconAnchor(offsetX=0.5, offsetY=0.5) {
|
|
706
|
+
return [offsetX, offsetY];
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* @function StyleUtils.getCircleDisplacement
|
|
710
|
+
* @description 获取圆圈的偏移
|
|
711
|
+
* @param {number} radius - 圆圈半径
|
|
712
|
+
* @param {number} offsetX - X方向偏移分数
|
|
713
|
+
* @param {number} offsetY - Y方向偏移分数
|
|
714
|
+
* @returns {Array.<number>}
|
|
715
|
+
*/
|
|
716
|
+
static getCircleDisplacement(radius, offsetX=0, offsetY=0) {
|
|
717
|
+
const dispX = radius*offsetX, dispY = radius*offsetY;
|
|
718
|
+
return [dispX, -dispY];
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* @function StyleUtils.getTextOffset
|
|
722
|
+
* @description 获取字体图标的偏移值
|
|
723
|
+
* @param {string} fontSize - 字体大小,如12px
|
|
724
|
+
* @param {number} offsetX - X方向偏移分数
|
|
725
|
+
* @param {number} offsetY - Y方向偏移分数
|
|
726
|
+
* @returns {Object}
|
|
727
|
+
*/
|
|
728
|
+
static getTextOffset(fontSize, offsetX=0, offsetY=0) {
|
|
729
|
+
const radius = fontSize.substr(0, fontSize.length - 2) / 2;
|
|
730
|
+
return {
|
|
731
|
+
x: radius*offsetX,
|
|
732
|
+
y: radius*offsetY
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* 获取文字标注对应的canvas
|
|
738
|
+
* @param style
|
|
739
|
+
* @returns {{canvas: *, width: number, height: number}}
|
|
740
|
+
*/
|
|
741
|
+
static getCanvas(style) {
|
|
742
|
+
let canvas;
|
|
743
|
+
if (style.canvas) {
|
|
744
|
+
if (document.querySelector("#" + style.canvas)) {
|
|
745
|
+
canvas = document.getElemntById(style.canvas);
|
|
746
|
+
} else {
|
|
747
|
+
canvas = this.createCanvas(style);
|
|
748
|
+
}
|
|
749
|
+
} else {
|
|
750
|
+
//不存在canvas,当前feature
|
|
751
|
+
canvas = this.createCanvas(style);
|
|
752
|
+
style.canvas = canvas.id;
|
|
753
|
+
}
|
|
754
|
+
canvas.style.display = "none";
|
|
755
|
+
var ctx = canvas.getContext("2d");
|
|
756
|
+
//行高
|
|
757
|
+
let lineHeight = Number(style.font.replace(/[^0-9]/ig, ""));
|
|
758
|
+
let textArray = style.text.split('\r\n');
|
|
759
|
+
let lenght = textArray.length;
|
|
760
|
+
//在改变canvas大小后再绘制。否则会被清除
|
|
761
|
+
ctx.font = style.font;
|
|
762
|
+
let size = this.drawRect(ctx, style, textArray, lineHeight, canvas);
|
|
763
|
+
this.positionY = padding;
|
|
764
|
+
if (lenght > 1) {
|
|
765
|
+
textArray.forEach(function (text, i) {
|
|
766
|
+
if (i !== 0) {
|
|
767
|
+
this.positionY = this.positionY + lineHeight;
|
|
768
|
+
}
|
|
769
|
+
this.canvasTextAutoLine(text, style, ctx, lineHeight, size.width);
|
|
770
|
+
}, this);
|
|
771
|
+
} else {
|
|
772
|
+
this.canvasTextAutoLine(textArray[0], style, ctx, lineHeight, size.width);
|
|
773
|
+
}
|
|
774
|
+
return {
|
|
775
|
+
canvas: canvas,
|
|
776
|
+
width: size.width,
|
|
777
|
+
height: size.height
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* 创建当前feature对应的canvas
|
|
782
|
+
* @param {Object} style
|
|
783
|
+
* @returns {HTMLElement}
|
|
784
|
+
*/
|
|
785
|
+
static createCanvas(style) {
|
|
786
|
+
let div = document.createElement('div');
|
|
787
|
+
document.body.appendChild(div);
|
|
788
|
+
let canvas = document.createElement('canvas');
|
|
789
|
+
canvas.id = style.canvas ? style.canvas : 'textCanvas' + Util.newGuid(8);
|
|
790
|
+
div.appendChild(canvas);
|
|
791
|
+
return canvas;
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* 绘制矩形边框背景
|
|
795
|
+
* @param ctx
|
|
796
|
+
* @param style
|
|
797
|
+
* @param textArray
|
|
798
|
+
* @param lineHeight
|
|
799
|
+
* @param canvas
|
|
800
|
+
* @returns {{width: number, height: number}}
|
|
801
|
+
*/
|
|
802
|
+
static drawRect(ctx, style, textArray, lineHeight, canvas) {
|
|
803
|
+
let backgroundFill = style.backgroundFill, maxWidth = style.maxWidth - doublePadding;
|
|
804
|
+
let width, height = 0, lineCount = 0, lineWidths = [];
|
|
805
|
+
//100的宽度,去掉左右两边3padding
|
|
806
|
+
textArray.forEach(function (arrText) {
|
|
807
|
+
let line = '', isOverMax;
|
|
808
|
+
lineCount++;
|
|
809
|
+
for (var n = 0; n < arrText.length; n++) {
|
|
810
|
+
let textLine = line + arrText[n];
|
|
811
|
+
let metrics = ctx.measureText(textLine);
|
|
812
|
+
let textWidth = metrics.width;
|
|
813
|
+
if ((textWidth > maxWidth && n > 0) || arrText[n] === '\n') {
|
|
814
|
+
line = arrText[n];
|
|
815
|
+
lineCount++;
|
|
816
|
+
//有换行,记录当前换行的width
|
|
817
|
+
isOverMax = true;
|
|
818
|
+
} else {
|
|
819
|
+
line = textLine;
|
|
820
|
+
width = textWidth;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
if (isOverMax) {
|
|
824
|
+
lineWidths.push(maxWidth);
|
|
825
|
+
} else {
|
|
826
|
+
lineWidths.push(width);
|
|
827
|
+
}
|
|
828
|
+
}, this);
|
|
829
|
+
width = this.getCanvasWidth(lineWidths, maxWidth);
|
|
830
|
+
height = lineCount * lineHeight;
|
|
831
|
+
height += doublePadding;
|
|
832
|
+
canvas.width = width;
|
|
833
|
+
canvas.height = height;
|
|
834
|
+
ctx.fillStyle = backgroundFill;
|
|
835
|
+
ctx.fillRect(0, 0, width, height);
|
|
836
|
+
return {
|
|
837
|
+
width: width,
|
|
838
|
+
height: height
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* 获取自适应的宽度(如果没有超过最大宽度,就用文字的宽度)
|
|
843
|
+
* @param lineWidths
|
|
844
|
+
* @param maxWidth
|
|
845
|
+
* @returns {number}
|
|
846
|
+
*/
|
|
847
|
+
static getCanvasWidth(lineWidths, maxWidth) {
|
|
848
|
+
let width = 0;
|
|
849
|
+
for (let i = 0; i < lineWidths.length; i++) {
|
|
850
|
+
let lineW = lineWidths[i];
|
|
851
|
+
if (lineW >= maxWidth) {
|
|
852
|
+
//有任何一行超过最大高度,就用最大高度
|
|
853
|
+
return maxWidth + doublePadding;
|
|
854
|
+
} else if (lineW > width) {
|
|
855
|
+
//自己换行,就要比较每行的最大宽度
|
|
856
|
+
width = lineW;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
return width + doublePadding;
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* 绘制文字,解决换行问题
|
|
863
|
+
* @param text
|
|
864
|
+
* @param style
|
|
865
|
+
* @param ctx
|
|
866
|
+
* @param lineHeight
|
|
867
|
+
*/
|
|
868
|
+
static canvasTextAutoLine(text, style, ctx, lineHeight, canvasWidth) {
|
|
869
|
+
// 字符分隔为数组
|
|
870
|
+
ctx.font = style.font;
|
|
871
|
+
let textAlign = style.textAlign;
|
|
872
|
+
let x = this.getPositionX(textAlign, canvasWidth);
|
|
873
|
+
let arrText = text.split('');
|
|
874
|
+
let line = '', fillColor = style.fillColor;
|
|
875
|
+
//每一行限制的高度
|
|
876
|
+
let maxWidth = style.maxWidth - doublePadding;
|
|
877
|
+
for (var n = 0; n < arrText.length; n++) {
|
|
878
|
+
let testLine = line + arrText[n];
|
|
879
|
+
let metrics = ctx.measureText(testLine);
|
|
880
|
+
let testWidth = metrics.width;
|
|
881
|
+
if ((testWidth > maxWidth && n > 0) || arrText[n] === '\n') {
|
|
882
|
+
ctx.fillStyle = fillColor;
|
|
883
|
+
ctx.textAlign = textAlign;
|
|
884
|
+
ctx.textBaseline = "top";
|
|
885
|
+
ctx.fillText(line, x, this.positionY);
|
|
886
|
+
line = arrText[n];
|
|
887
|
+
this.positionY += lineHeight;
|
|
888
|
+
} else {
|
|
889
|
+
line = testLine;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
ctx.fillStyle = fillColor;
|
|
893
|
+
ctx.textAlign = textAlign;
|
|
894
|
+
ctx.textBaseline = "top";
|
|
895
|
+
ctx.fillText(line, x, this.positionY);
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* 得到绘制的起点位置,根据align不同,位置也不同
|
|
899
|
+
* @param textAlign
|
|
900
|
+
* @returns {number}
|
|
901
|
+
*/
|
|
902
|
+
static getPositionX(textAlign, canvasWidth) {
|
|
903
|
+
let x;
|
|
904
|
+
let width = canvasWidth - doublePadding; //减去padding
|
|
905
|
+
switch (textAlign) {
|
|
906
|
+
case 'center':
|
|
907
|
+
x = width / 2;
|
|
908
|
+
break;
|
|
909
|
+
case 'right':
|
|
910
|
+
x = width;
|
|
911
|
+
break;
|
|
912
|
+
default:
|
|
913
|
+
x = 8;
|
|
914
|
+
break;
|
|
915
|
+
}
|
|
916
|
+
return x;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* @function StyleUtils.hexToRgb
|
|
921
|
+
* @description 将16进制的颜色,转换成rgb格式
|
|
922
|
+
* @param {string} hexColor 16进制颜色
|
|
923
|
+
* @returns {string} rgb格式的颜色
|
|
924
|
+
*/
|
|
925
|
+
static hexToRgb(hexColor) {
|
|
926
|
+
if (!hexColor) {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
var s = hexColor.replace('#', '').split('');
|
|
930
|
+
var rgb = [s[0] + s[1], s[2] + s[3], s[4] + s[5]];
|
|
931
|
+
rgb = rgb.map(function (hex) {
|
|
932
|
+
return parseInt(hex, 16);
|
|
933
|
+
});
|
|
934
|
+
return rgb;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* @function StyleUtils.formatRGB
|
|
939
|
+
* @description 将颜色数组转换成标准的rgb颜色格式
|
|
940
|
+
* @param {Array} colorArray - 颜色数组
|
|
941
|
+
* @returns {string} 'rgb(0,0,0)'或者 'rgba(0,0,0,0)'
|
|
942
|
+
*/
|
|
943
|
+
static formatRGB(colorArray) {
|
|
944
|
+
let rgb;
|
|
945
|
+
if (colorArray.length === 3) {
|
|
946
|
+
rgb = 'rgb(';
|
|
947
|
+
colorArray.forEach(function (color, index) {
|
|
948
|
+
index === 2 ? rgb += color : rgb += color + ',';
|
|
949
|
+
});
|
|
950
|
+
} else {
|
|
951
|
+
rgb = 'rgba(';
|
|
952
|
+
colorArray.forEach(function (color, index) {
|
|
953
|
+
index === 3 ? rgb += color : rgb += color + ',';
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
rgb += ")"
|
|
957
|
+
return rgb;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* @function StyleUtils.getCanvasFromSVG
|
|
962
|
+
* @description 将SVG转换成Canvas
|
|
963
|
+
* @param {string} svgUrl - 颜色数组
|
|
964
|
+
* @param {Object} divDom - div的dom对象
|
|
965
|
+
* @param {function} callBack - 转换成功执行的回调函数
|
|
966
|
+
*/
|
|
967
|
+
static async getCanvasFromSVG(svgUrl, divDom, callBack) {
|
|
968
|
+
//一个图层对应一个canvas
|
|
969
|
+
const canvgs = window.canvg && window.canvg.default ? window.canvg.default : Canvg;
|
|
970
|
+
let canvas = document.createElement('canvas');
|
|
971
|
+
canvas.id = 'dataviz-canvas-' + Util.newGuid(8);
|
|
972
|
+
canvas.style.display = "none";
|
|
973
|
+
divDom.appendChild(canvas);
|
|
974
|
+
try {
|
|
975
|
+
const ctx = canvas.getContext('2d');
|
|
976
|
+
const v = await canvgs.from(ctx, svgUrl, {
|
|
977
|
+
ignoreMouse: true,
|
|
978
|
+
ignoreAnimation: true,
|
|
979
|
+
forceRedraw: () => false
|
|
980
|
+
})
|
|
981
|
+
v.start();
|
|
982
|
+
if (canvas.width > 300 || canvas.height > 300) {
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
callBack(canvas);
|
|
986
|
+
} catch (e) {
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* @function StyleUtils.stopCanvg
|
|
993
|
+
* @description 调用Canvg实例的stop();
|
|
994
|
+
*/
|
|
995
|
+
static stopCanvg() {
|
|
996
|
+
this.canvgsV.forEach(v => v.stop());
|
|
997
|
+
this.canvgsV = [];
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
/**
|
|
1001
|
+
* @function StyleUtils.getMarkerDefaultStyle 获取默认标注图层feature的样式
|
|
1002
|
+
* @param {string} featureType feature的类型
|
|
1003
|
+
* @param {string} server 当前地图前缀
|
|
1004
|
+
* @returns {Object} style对象
|
|
1005
|
+
*/
|
|
1006
|
+
static getMarkerDefaultStyle(featureType, server) {
|
|
1007
|
+
let style;
|
|
1008
|
+
switch (featureType) {
|
|
1009
|
+
case 'POINT':
|
|
1010
|
+
style = {
|
|
1011
|
+
src: `${server}apps/dataviz/static/imgs/markers/mark_red.png`,
|
|
1012
|
+
scale: 1,
|
|
1013
|
+
anchor: [0.5, 1]
|
|
1014
|
+
};
|
|
1015
|
+
break;
|
|
1016
|
+
case 'LINE':
|
|
1017
|
+
case 'LINESTRING':
|
|
1018
|
+
case 'MULTILINESTRING':
|
|
1019
|
+
style = {
|
|
1020
|
+
strokeColor: '#3498db',
|
|
1021
|
+
strokeOpacity: 1,
|
|
1022
|
+
strokeWidth: 5,
|
|
1023
|
+
lineCap: 'round',
|
|
1024
|
+
lineDash: 'solid'
|
|
1025
|
+
};
|
|
1026
|
+
break;
|
|
1027
|
+
case 'REGION':
|
|
1028
|
+
case 'POLYGON':
|
|
1029
|
+
case 'MULTIPOLYGON':
|
|
1030
|
+
style = {
|
|
1031
|
+
fillColor: '#1abd9c',
|
|
1032
|
+
fillOpacity: 1,
|
|
1033
|
+
strokeColor: '#3498db',
|
|
1034
|
+
strokeOpacity: 1,
|
|
1035
|
+
strokeWidth: 3,
|
|
1036
|
+
lineCap: 'round',
|
|
1037
|
+
lineDash: 'solid'
|
|
1038
|
+
};
|
|
1039
|
+
break;
|
|
1040
|
+
}
|
|
1041
|
+
return style;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
/**
|
|
1045
|
+
* @function StyleUtils.getOpenlayerStyle 获取专题图对应的openlayers格式的style
|
|
1046
|
+
* @param {string} styleParams 样式参数
|
|
1047
|
+
* @param {string} featureType feature类型
|
|
1048
|
+
* @param {boolean} isRank 是否为等级符号
|
|
1049
|
+
* @returns {Promise<ol.style.Style>}
|
|
1050
|
+
*/
|
|
1051
|
+
static async getOpenlayersStyle(styleParams, featureType, isRank) {
|
|
1052
|
+
let style;
|
|
1053
|
+
if (styleParams.type === "BASIC_POINT") {
|
|
1054
|
+
style = await this.toOpenLayersStyle(styleParams, featureType);
|
|
1055
|
+
} else if (styleParams.type === "SYMBOL_POINT") {
|
|
1056
|
+
style = this.getSymbolStyle(styleParams, isRank);
|
|
1057
|
+
} else if (styleParams.type === "SVG_POINT") {
|
|
1058
|
+
style = await this.getSVGStyle(styleParams);
|
|
1059
|
+
} else if (styleParams.type === 'IMAGE_POINT') {
|
|
1060
|
+
style = this.getImageStyle(styleParams);
|
|
1061
|
+
}
|
|
1062
|
+
return style;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/**
|
|
1066
|
+
* @function StyleUtils.getSymbolStyle 获取符号样式
|
|
1067
|
+
* @param {Object} parameters - 样式参数
|
|
1068
|
+
* @returns {Object} style对象
|
|
1069
|
+
*/
|
|
1070
|
+
static getSymbolStyle(parameters, isRank) {
|
|
1071
|
+
let text = '';
|
|
1072
|
+
if (parameters.unicode) {
|
|
1073
|
+
text = String.fromCharCode(parseInt(parameters.unicode.replace(/^&#x/, ''), 16));
|
|
1074
|
+
}
|
|
1075
|
+
// 填充色 + 透明度
|
|
1076
|
+
let fillColor = StyleUtils.hexToRgb(parameters.fillColor);
|
|
1077
|
+
fillColor.push(parameters.fillOpacity);
|
|
1078
|
+
// 边框充色 + 透明度
|
|
1079
|
+
let strokeColor = StyleUtils.hexToRgb(parameters.strokeColor);
|
|
1080
|
+
strokeColor.push(parameters.strokeOpacity);
|
|
1081
|
+
|
|
1082
|
+
let fontSize = isRank ? 2 * parameters.radius + "px" : parameters.fontSize;
|
|
1083
|
+
|
|
1084
|
+
const {offsetX, offsetY, rotation=0} = parameters;
|
|
1085
|
+
const offset = StyleUtils.getTextOffset(fontSize, offsetX, offsetY);
|
|
1086
|
+
return new Style({
|
|
1087
|
+
text: new Text({
|
|
1088
|
+
text: text,
|
|
1089
|
+
font: fontSize + " supermapol-icons",
|
|
1090
|
+
placement: 'point',
|
|
1091
|
+
textAlign: 'center',
|
|
1092
|
+
fill: new FillStyle({
|
|
1093
|
+
color: fillColor
|
|
1094
|
+
}),
|
|
1095
|
+
backgroundFill: new FillStyle({
|
|
1096
|
+
color: [0, 0, 0, 0]
|
|
1097
|
+
}),
|
|
1098
|
+
stroke: new StrokeStyle({
|
|
1099
|
+
width: parameters.strokeWidth || 0.000001,
|
|
1100
|
+
color: strokeColor
|
|
1101
|
+
}),
|
|
1102
|
+
offsetX: offset.x,
|
|
1103
|
+
offsetY: offset.y,
|
|
1104
|
+
rotation
|
|
1105
|
+
})
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
/**
|
|
1109
|
+
* @function StyleUtils.getSVGStyle 获取svg的样式
|
|
1110
|
+
* @param {Object} styleParams - 样式参数
|
|
1111
|
+
* @returns {Promise<ol.style.Style>}
|
|
1112
|
+
*/
|
|
1113
|
+
static async getSVGStyle(styleParams) {
|
|
1114
|
+
let style, that = this;
|
|
1115
|
+
if (!that.svgDiv) {
|
|
1116
|
+
that.svgDiv = document.createElement('div');
|
|
1117
|
+
document.body.appendChild(that.svgDiv);
|
|
1118
|
+
}
|
|
1119
|
+
const { url, radius, offsetX, offsetY, fillOpacity, rotation } = styleParams;
|
|
1120
|
+
let anchor = this.getIconAnchor(offsetX, offsetY);
|
|
1121
|
+
await StyleUtils.getCanvasFromSVG(url, that.svgDiv, function (canvas) {
|
|
1122
|
+
style = new Style({
|
|
1123
|
+
image: new Icon({
|
|
1124
|
+
img: that.setColorToCanvas(canvas, styleParams),
|
|
1125
|
+
scale: 2 * radius / canvas.width,
|
|
1126
|
+
imgSize: [canvas.width, canvas.height],
|
|
1127
|
+
anchor: anchor || [0.5, 0.5],
|
|
1128
|
+
opacity: fillOpacity,
|
|
1129
|
+
anchorOrigin: 'bottom-right',
|
|
1130
|
+
rotation
|
|
1131
|
+
})
|
|
1132
|
+
});
|
|
1133
|
+
});
|
|
1134
|
+
return style;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
/**
|
|
1138
|
+
* @function StyleUtils.setColorToCanvas 将颜色,透明度等样式设置到canvas上
|
|
1139
|
+
* @param {Object} canvas - 渲染的canvas对象
|
|
1140
|
+
* @param {Object} parameters - 样式参数
|
|
1141
|
+
* @returns {Object} style对象
|
|
1142
|
+
*/
|
|
1143
|
+
static setColorToCanvas(canvas, parameters) {
|
|
1144
|
+
let context = canvas.getContext('2d');
|
|
1145
|
+
let fillColor = StyleUtils.hexToRgb(parameters.fillColor);
|
|
1146
|
+
fillColor && fillColor.push(parameters.fillOpacity);
|
|
1147
|
+
let strokeColor = StyleUtils.hexToRgb(parameters.strokeColor);
|
|
1148
|
+
strokeColor && strokeColor.push(parameters.strokeOpacity);
|
|
1149
|
+
context.fillStyle = StyleUtils.formatRGB(fillColor);
|
|
1150
|
+
context.fill();
|
|
1151
|
+
context.strokeStyle = StyleUtils.formatRGB(strokeColor);
|
|
1152
|
+
context.lineWidth = parameters.strokeWidth;
|
|
1153
|
+
context.stroke();
|
|
1154
|
+
return canvas;
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* @function StyleUtils.getImageStyle 获取图片样式
|
|
1158
|
+
* @param {Object} styleParams - 样式参数
|
|
1159
|
+
* @returns {Object} style对象
|
|
1160
|
+
*/
|
|
1161
|
+
static getImageStyle(styleParams) {
|
|
1162
|
+
let size = styleParams.imageInfo.size,
|
|
1163
|
+
scale = 2 * styleParams.radius / size.w;
|
|
1164
|
+
let imageInfo = styleParams.imageInfo;
|
|
1165
|
+
let imgDom = imageInfo.img;
|
|
1166
|
+
if (!imgDom || !imgDom.src) {
|
|
1167
|
+
imgDom = new Image();
|
|
1168
|
+
//要组装成完整的url
|
|
1169
|
+
imgDom.src = imageInfo.url;
|
|
1170
|
+
}
|
|
1171
|
+
const { offsetX, offsetY, rotation } = styleParams;
|
|
1172
|
+
let anchor = this.getIconAnchor(offsetX, offsetY);
|
|
1173
|
+
return new Style({
|
|
1174
|
+
image: new Icon({
|
|
1175
|
+
img: imgDom,
|
|
1176
|
+
scale,
|
|
1177
|
+
imgSize: [size.w, size.h],
|
|
1178
|
+
anchor: anchor || [0.5, 0.5],
|
|
1179
|
+
anchorOrigin: 'bottom-right',
|
|
1180
|
+
rotation
|
|
1181
|
+
})
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
/**
|
|
1185
|
+
* @function StyleUtils.getRoadPath 获取道路样式
|
|
1186
|
+
* @param {Object} style - 样式参数
|
|
1187
|
+
* @param {Object} outlineStyle - 轮廓样式参数
|
|
1188
|
+
* @returns {Object} style对象
|
|
1189
|
+
*/
|
|
1190
|
+
static getRoadPath(style, outlineStyle) {
|
|
1191
|
+
const { strokeWidth=ZERO, lineCap, strokeColor, strokeOpacity } = style;
|
|
1192
|
+
// 道路线都是solid
|
|
1193
|
+
let strokeColorArray = this.hexToRgb(strokeColor);
|
|
1194
|
+
strokeColorArray && strokeColorArray.push(strokeOpacity);
|
|
1195
|
+
var stroke = new Style({
|
|
1196
|
+
stroke: new StrokeStyle({
|
|
1197
|
+
width: strokeWidth || ZERO,
|
|
1198
|
+
color: strokeColorArray,
|
|
1199
|
+
lineCap: lineCap || 'round',
|
|
1200
|
+
lineDash: [0]
|
|
1201
|
+
})
|
|
1202
|
+
});
|
|
1203
|
+
|
|
1204
|
+
const { strokeColor: outlineColor } = outlineStyle;
|
|
1205
|
+
let outlineColorArray = this.hexToRgb(outlineColor);
|
|
1206
|
+
// opacity使用style的透明度。保持两根线透明度一致
|
|
1207
|
+
outlineColorArray && outlineColorArray.push(strokeOpacity);
|
|
1208
|
+
let outlineWidth = outlineStyle.strokeWidth || (strokeWidth === 0 ? ZERO : strokeWidth + 2); //外部宽度=内部样式宽度 + 2
|
|
1209
|
+
var outlineStroke = new Style({
|
|
1210
|
+
stroke: new StrokeStyle({
|
|
1211
|
+
width: outlineWidth, //外部宽度=内部样式宽度 + 2
|
|
1212
|
+
color: outlineColorArray,
|
|
1213
|
+
lineCap: lineCap || 'round',
|
|
1214
|
+
lineDash: [0]
|
|
1215
|
+
})
|
|
1216
|
+
});
|
|
1217
|
+
return [outlineStroke, stroke];
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* @function StyleUtils.getPathway 获取铁路样式
|
|
1221
|
+
* @param {Object} style - 样式参数
|
|
1222
|
+
* @param {Object} outlineStyle - 轮廓样式参数
|
|
1223
|
+
* @returns {Object} style对象
|
|
1224
|
+
*/
|
|
1225
|
+
static getPathway(style, outlineStyle) {
|
|
1226
|
+
let { strokeWidth=ZERO, strokeColor, strokeOpacity } = style;
|
|
1227
|
+
// 道路线都是solid, lineCap都是直角
|
|
1228
|
+
const lineDash = (w => [w, w + strokeWidth * 2])(4 * strokeWidth), lineCap= 'square';
|
|
1229
|
+
let strokeColorArray = this.hexToRgb(strokeColor);
|
|
1230
|
+
strokeColorArray && strokeColorArray.push(strokeOpacity);
|
|
1231
|
+
var stroke = new Style({
|
|
1232
|
+
stroke: new StrokeStyle({
|
|
1233
|
+
width: strokeWidth*0.5 || ZERO,
|
|
1234
|
+
color: strokeColorArray,
|
|
1235
|
+
lineCap,
|
|
1236
|
+
lineDash
|
|
1237
|
+
})
|
|
1238
|
+
});
|
|
1239
|
+
|
|
1240
|
+
const { strokeColor: outlineColor } = outlineStyle;
|
|
1241
|
+
let outlineColorArray = this.hexToRgb(outlineColor);
|
|
1242
|
+
// opacity使用style的透明度。保持两根线透明度一致
|
|
1243
|
+
outlineColorArray && outlineColorArray.push(strokeOpacity);
|
|
1244
|
+
var outlineStroke = new Style({
|
|
1245
|
+
stroke: new StrokeStyle({
|
|
1246
|
+
width: strokeWidth || ZERO,
|
|
1247
|
+
color: outlineColorArray,
|
|
1248
|
+
lineCap
|
|
1249
|
+
})
|
|
1250
|
+
});
|
|
1251
|
+
return [outlineStroke, stroke];
|
|
1252
|
+
}
|
|
1253
|
+
}
|