@supermapgis/iclient-ol 11.1.2
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 +99 -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 +478 -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 +121806 -0
- package/dist/iclient-openlayers-es6.min.js +8 -0
- package/dist/iclient-openlayers.css +668 -0
- package/dist/iclient-openlayers.js +132335 -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 +125 -0
- package/mapping/SuperMapCloud.js +56 -0
- package/mapping/Tianditu.js +152 -0
- package/mapping/TileSuperMapRest.js +358 -0
- package/mapping/WebMap.js +5185 -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 +97 -0
- package/overlay/Graph.js +436 -0
- package/overlay/GraphMap.js +91 -0
- package/overlay/Graphic.js +587 -0
- package/overlay/HeatMap.js +444 -0
- package/overlay/Label.js +964 -0
- package/overlay/Mapv.js +146 -0
- package/overlay/Range.js +127 -0
- package/overlay/RankSymbol.js +94 -0
- package/overlay/Turf.js +298 -0
- package/overlay/Unique.js +123 -0
- package/overlay/VectorTileSuperMapRest.js +466 -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 +63 -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 +410 -0
- package/overlay/mapv/index.js +5 -0
- package/overlay/theme/GeoFeature.js +275 -0
- package/overlay/theme/Theme.js +585 -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 +375 -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 +29 -0
- package/services/AddressMatchService.js +60 -0
- package/services/ChartService.js +74 -0
- package/services/DataFlowService.js +118 -0
- package/services/DatasetService.js +104 -0
- package/services/DatasourceService.js +76 -0
- package/services/FeatureService.js +196 -0
- package/services/FieldService.js +53 -0
- package/services/GeoprocessingService.js +156 -0
- package/services/GridCellInfosService.js +53 -0
- package/services/ImageCollectionService.js +92 -0
- package/services/ImageService.js +69 -0
- package/services/KnowledgeGraphService.js +82 -0
- package/services/LayerInfoService.js +85 -0
- package/services/MapService.js +85 -0
- package/services/MeasureService.js +77 -0
- package/services/NetworkAnalyst3DService.js +88 -0
- package/services/NetworkAnalystService.js +252 -0
- package/services/ProcessingService.js +478 -0
- package/services/QueryService.js +116 -0
- package/services/ServiceBase.js +26 -0
- package/services/SpatialAnalystService.js +432 -0
- package/services/ThemeService.js +50 -0
- package/services/TrafficTransferAnalystService.js +88 -0
- package/services/WebPrintingJobService.js +112 -0
- package/services/index.js +27 -0
package/overlay/Label.js
ADDED
|
@@ -0,0 +1,964 @@
|
|
|
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} from '@supermapgis/iclient-common/commontypes/Util';
|
|
5
|
+
import { GeoText } from '@supermapgis/iclient-common/commontypes/geometry/GeoText';
|
|
6
|
+
import { Bounds } from '@supermapgis/iclient-common/commontypes/Bounds';
|
|
7
|
+
import { ShapeFactory } from '@supermapgis/iclient-common/overlay/feature/ShapeFactory';
|
|
8
|
+
import { ThemeVector } from '@supermapgis/iclient-common/overlay/ThemeVector';
|
|
9
|
+
import { Vector as FeatureVector } from '@supermapgis/iclient-common/commontypes/Vector';
|
|
10
|
+
import {
|
|
11
|
+
GeoFeature
|
|
12
|
+
} from './theme/GeoFeature';
|
|
13
|
+
import Point from 'ol/geom/Point';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @class Label
|
|
17
|
+
* @browsernamespace ol.source
|
|
18
|
+
* @category Visualization Theme
|
|
19
|
+
* @classdesc 标签专题图图层源。
|
|
20
|
+
* @modulecategory Overlay
|
|
21
|
+
* @param {string} name - 名称。
|
|
22
|
+
* @param {Object} opt_options - 参数。
|
|
23
|
+
* @param {ol.Map} opt_options.map - 当前 Map 对象。
|
|
24
|
+
* @param {string} [opt_options.id] - 专题图层 ID。默认使用 CommonUtil.createUniqueID("themeLayer_") 创建专题图层 ID。
|
|
25
|
+
* @param {number} [opt_options.opacity=1] - 图层透明度。
|
|
26
|
+
* @param {string|Object} [opt_options.attributions] - 版权信息。
|
|
27
|
+
* @param {string} [opt_options.logo] - Logo(openLayers 5.0.0 及更高版本不再支持此参数)。
|
|
28
|
+
* @param {ol.proj.Projection} [opt_options.projection] - 投影信息。
|
|
29
|
+
* @param {number} [opt_options.ratio=1.5] - 视图比,1 表示画布是地图视口的大小,2 表示地图视口的宽度和高度的两倍,依此类推。必须是1或更高。
|
|
30
|
+
* @param {Array.<number>} [opt_options.resolutions] - 分辨率数组。
|
|
31
|
+
* @param {ol.source.State} [opt_options.state] - 资源状态。
|
|
32
|
+
* @param {string} [opt_options.themeField] - 指定创建专题图字段。
|
|
33
|
+
* @param {Object} [opt_options.style] - 专题图样式。
|
|
34
|
+
* @param {Object} [opt_options.styleGroups] - 各专题类型样式组。
|
|
35
|
+
* @param {boolean} [opt_options.isHoverAble = false] - 是否开启 hover 事件。
|
|
36
|
+
* @param {Object} [opt_options.highlightStyle] - 开启 hover 事件后,触发的样式风格。
|
|
37
|
+
* @extends {GeoFeature}
|
|
38
|
+
* @usage
|
|
39
|
+
*/
|
|
40
|
+
export class Label extends GeoFeature {
|
|
41
|
+
|
|
42
|
+
constructor(name, opt_options) {
|
|
43
|
+
super(name, opt_options);
|
|
44
|
+
this.isOverLay = opt_options.isOverLay != null ? opt_options.isOverLay : true;
|
|
45
|
+
this.isAvoid = opt_options.isAvoid != null ? opt_options.isAvoid : true;
|
|
46
|
+
|
|
47
|
+
this.style = opt_options.style;
|
|
48
|
+
this.themeField = opt_options.themeField;
|
|
49
|
+
this.styleGroups = opt_options.styleGroups;
|
|
50
|
+
|
|
51
|
+
this.defaultStyle = {
|
|
52
|
+
//默认文本样式
|
|
53
|
+
fontColor: "#000000",
|
|
54
|
+
fontOpacity: 1,
|
|
55
|
+
fontSize: "12px",
|
|
56
|
+
fontStyle: "normal",
|
|
57
|
+
fontWeight: "normal",
|
|
58
|
+
labelAlign: "cm",
|
|
59
|
+
labelXOffset: 0,
|
|
60
|
+
labelYOffset: 0,
|
|
61
|
+
labelRotation: 0,
|
|
62
|
+
|
|
63
|
+
//默认背景框样式
|
|
64
|
+
fill: false,
|
|
65
|
+
fillColor: "#ee9900",
|
|
66
|
+
fillOpacity: 0.4,
|
|
67
|
+
stroke: false,
|
|
68
|
+
strokeColor: "#ee9900",
|
|
69
|
+
strokeOpacity: 1,
|
|
70
|
+
strokeWidth: 1,
|
|
71
|
+
strokeLinecap: "round",
|
|
72
|
+
strokeDashstyle: "solid",
|
|
73
|
+
|
|
74
|
+
//对用户隐藏但必须保持此值的属性
|
|
75
|
+
//cursor: "pointer",
|
|
76
|
+
labelSelect: true,
|
|
77
|
+
|
|
78
|
+
//用 _isGeoTextStrategyStyle 标记此style,携带此类style的要素特指GeoText策略中的标签要素
|
|
79
|
+
_isGeoTextStrategyStyle: true
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
//获取标签像素 bounds 的方式。0 - 表示通过文本类容和文本风格计算获取像素范围,现在支持中文、英文; 1 - 表示通过绘制的文本标签获取像素范围,支持各个语种的文字范围获取,但性能消耗较大(尤其是采用SVG渲染)。默认值为0。
|
|
83
|
+
this.getPxBoundsMode = 0;
|
|
84
|
+
|
|
85
|
+
this.labelFeatures = [];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @function Label.prototype.destroy
|
|
90
|
+
* @description 释放资源,将引用资源的属性置空。
|
|
91
|
+
*/
|
|
92
|
+
destroy() {
|
|
93
|
+
this.style = null;
|
|
94
|
+
this.themeField = null;
|
|
95
|
+
this.styleGroups = null;
|
|
96
|
+
super.destroy();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @private
|
|
101
|
+
* @function Label.prototype.createThematicFeature
|
|
102
|
+
* @description 创建专题要素。
|
|
103
|
+
* @param {FeatureVector} feature - 矢量要素。
|
|
104
|
+
* @returns {FeatureThemeVector} 专题图矢量要素。
|
|
105
|
+
*/
|
|
106
|
+
createThematicFeature(feature) {
|
|
107
|
+
//赋 style
|
|
108
|
+
var style = this.getStyleByData(feature);
|
|
109
|
+
//创建专题要素时的可选参数
|
|
110
|
+
var options = {};
|
|
111
|
+
options.nodesClipPixel = this.nodesClipPixel;
|
|
112
|
+
options.isHoverAble = this.isHoverAble;
|
|
113
|
+
options.isMultiHover = this.isMultiHover;
|
|
114
|
+
options.isClickAble = this.isClickAble;
|
|
115
|
+
options.highlightStyle = ShapeFactory.transformStyle(this.highlightStyle);
|
|
116
|
+
//将数据转为专题要素(Vector)
|
|
117
|
+
var thematicFeature = new ThemeVector(feature, this, ShapeFactory.transformStyle(style), options);
|
|
118
|
+
//直接添加图形到渲染器
|
|
119
|
+
for (var m = 0; m < thematicFeature.shapes.length; m++) {
|
|
120
|
+
this.renderer.addShape(thematicFeature.shapes[m]);
|
|
121
|
+
}
|
|
122
|
+
return thematicFeature;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @function Label.prototype.redrawThematicFeatures
|
|
128
|
+
* @description 重绘所有专题要素。
|
|
129
|
+
* 此方法包含绘制专题要素的所有步骤,包含用户数据到专题要素的转换,抽稀,缓存等步骤。
|
|
130
|
+
* 地图漫游时调用此方法进行图层刷新。
|
|
131
|
+
* @param {Array.<number>} bounds - 重绘范围。
|
|
132
|
+
*/
|
|
133
|
+
redrawThematicFeatures(bounds) {
|
|
134
|
+
if (this.features.length > 0 && this.labelFeatures.length === 0) {
|
|
135
|
+
var feats = this.setLabelsStyle(this.features);
|
|
136
|
+
for (var i = 0, len = feats.length; i < len; i++) {
|
|
137
|
+
this.labelFeatures.push(feats[i]);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
this.features = this.getDrawnLabels(this.labelFeatures);
|
|
141
|
+
super.redrawThematicFeatures.call(this, bounds);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* @function Label.prototype.removeFeatures
|
|
145
|
+
* @description 从专题图中删除 feature。这个函数删除所有传递进来的矢量要素。
|
|
146
|
+
* @param {(Array.<FeatureVector>|FeatureVector|Function)} features - 待删除的要素对象或用于过滤的回调函数。
|
|
147
|
+
*/
|
|
148
|
+
removeFeatures(features) { // eslint-disable-line no-unused-vars
|
|
149
|
+
this.labelFeatures = [];
|
|
150
|
+
super.removeFeatures.call(this, features);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @function Label.prototype.removeAllFeatures
|
|
155
|
+
* @description 清除当前图层所有的矢量要素。
|
|
156
|
+
*/
|
|
157
|
+
removeAllFeatures() {
|
|
158
|
+
this.labelFeatures = [];
|
|
159
|
+
super.removeAllFeatures.call(this, arguments);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* @function Label.prototype.getDrawnLabels
|
|
163
|
+
* @description 获取经(压盖)处理后将要绘制在图层上的标签要素。
|
|
164
|
+
* @param {Array.<FeatureVector>} labelFeatures - 所有标签要素的数组。
|
|
165
|
+
* @returns {Array.<FeatureVector>} 最终要绘制的标签要素数组。
|
|
166
|
+
*/
|
|
167
|
+
getDrawnLabels(labelFeatures) {
|
|
168
|
+
var feas = [], //最终要绘制的标签要素集
|
|
169
|
+
fea, //最终要绘制的标签要素
|
|
170
|
+
fi, //临时标签要素,用户的第i个标签
|
|
171
|
+
labelsB = [], //不产生压盖的标签要素范围集
|
|
172
|
+
styTmp, //用于临时存储要素style的变量
|
|
173
|
+
feaSty, //标签要素最终的style
|
|
174
|
+
// styleTemp用于屏蔽文本style中带有偏移性质style属性,偏移已经在计算bounds的过程中参与了运算,
|
|
175
|
+
// 所以在最终按照bounds来绘制标签时,需屏蔽style中带有偏移性质属性,否则文本的偏移量将扩大一倍。
|
|
176
|
+
styleTemp = {
|
|
177
|
+
labelAlign: "cm",
|
|
178
|
+
labelXOffset: 0,
|
|
179
|
+
labelYOffset: 0
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
var map = this.map;
|
|
183
|
+
var mapSize = map.getSize();
|
|
184
|
+
mapSize = {
|
|
185
|
+
x: mapSize[0],
|
|
186
|
+
y: mapSize[1]
|
|
187
|
+
};
|
|
188
|
+
var zoom = map.getView().getZoom();
|
|
189
|
+
//对用户的每个标签要素进行处理与判断
|
|
190
|
+
for (var i = 0, len = labelFeatures.length; i < len; i++) {
|
|
191
|
+
fi = labelFeatures[i];
|
|
192
|
+
//检查fi的style在避让中是否被改变,如果改变,重新设置要素的style
|
|
193
|
+
if (fi.isStyleChange) {
|
|
194
|
+
fi = this.setStyle(fi);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
//标签最终的中心点像素位置 (偏移后)
|
|
198
|
+
var loc = this.getLabelPxLocation(fi);
|
|
199
|
+
|
|
200
|
+
//过滤掉地图范围外的标签 (偏移后)
|
|
201
|
+
if ((loc.x >= 0 && loc.x <= mapSize.x) && (loc.y >= 0 && loc.y <= mapSize.y)) {
|
|
202
|
+
//根据当前地图缩放级别过滤标签
|
|
203
|
+
if (fi.style.minZoomLevel > -1) {
|
|
204
|
+
if (zoom <= fi.style.minZoomLevel) {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (fi.style.maxZoomLevel > -1) {
|
|
209
|
+
if (zoom > fi.style.maxZoomLevel) {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
//计算标签bounds
|
|
215
|
+
var boundsQuad = null;
|
|
216
|
+
if (fi.isStyleChange) {
|
|
217
|
+
fi.isStyleChange = null;
|
|
218
|
+
boundsQuad = this.calculateLabelBounds(fi, loc);
|
|
219
|
+
} else {
|
|
220
|
+
if (fi.geometry.bsInfo.w && fi.geometry.bsInfo.h) {
|
|
221
|
+
//使用calculateLabelBounds2可以提高bounds的计算效率,尤其是在getPxBoundsMode = 1时
|
|
222
|
+
boundsQuad = this.calculateLabelBounds2(fi, loc);
|
|
223
|
+
} else {
|
|
224
|
+
boundsQuad = this.calculateLabelBounds(fi, loc);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
//避让处理 -start
|
|
229
|
+
var mapViewBounds = new Bounds(0, mapSize.y, mapSize.x, 0), //地图像素范围
|
|
230
|
+
quadlen = boundsQuad.length;
|
|
231
|
+
|
|
232
|
+
if (this.isAvoid) {
|
|
233
|
+
var avoidInfo = this.getAvoidInfo(mapViewBounds, boundsQuad); //避让信息
|
|
234
|
+
|
|
235
|
+
if (avoidInfo) {
|
|
236
|
+
//横向(x方向)上的避让
|
|
237
|
+
if (avoidInfo.aspectW === "left") {
|
|
238
|
+
fi.style.labelXOffset += avoidInfo.offsetX;
|
|
239
|
+
|
|
240
|
+
for (let j = 0; j < quadlen; j++) {
|
|
241
|
+
boundsQuad[j].x += avoidInfo.offsetX;
|
|
242
|
+
}
|
|
243
|
+
} else if (avoidInfo.aspectW === "right") {
|
|
244
|
+
fi.style.labelXOffset += (-avoidInfo.offsetX);
|
|
245
|
+
|
|
246
|
+
for (let j = 0; j < quadlen; j++) {
|
|
247
|
+
boundsQuad[j].x += (-avoidInfo.offsetX);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
//纵向(y方向)上的避让
|
|
252
|
+
if (avoidInfo.aspectH === "top") {
|
|
253
|
+
fi.style.labelYOffset += avoidInfo.offsetY;
|
|
254
|
+
|
|
255
|
+
for (let j = 0; j < quadlen; j++) {
|
|
256
|
+
boundsQuad[j].y += avoidInfo.offsetY;
|
|
257
|
+
}
|
|
258
|
+
} else if (avoidInfo.aspectH === "bottom") {
|
|
259
|
+
fi.style.labelYOffset += (-avoidInfo.offsetY);
|
|
260
|
+
|
|
261
|
+
for (let j = 0; j < quadlen; j++) {
|
|
262
|
+
boundsQuad[j].y += (-avoidInfo.offsetY);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
//如果style发生变化,记录下来
|
|
267
|
+
fi.isStyleChange = true;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
//避让处理 -end
|
|
271
|
+
|
|
272
|
+
//压盖处理 -start
|
|
273
|
+
if (this.isOverLay) {
|
|
274
|
+
//是否压盖
|
|
275
|
+
var isOL = false;
|
|
276
|
+
if (i != 0) {
|
|
277
|
+
for (let j = 0; j < labelsB.length; j++) {
|
|
278
|
+
//压盖判断
|
|
279
|
+
if (this.isQuadrilateralOverLap(boundsQuad, labelsB[j])) {
|
|
280
|
+
isOL = true;
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (isOL) {
|
|
287
|
+
continue;
|
|
288
|
+
} else {
|
|
289
|
+
labelsB.push(boundsQuad);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
//压盖处理 -end
|
|
293
|
+
|
|
294
|
+
//将标签像素范围转为地理范围
|
|
295
|
+
var geoBs = [];
|
|
296
|
+
for (let j = 0; j < quadlen - 1; j++) {
|
|
297
|
+
geoBs.push(map.getCoordinateFromPixel([boundsQuad[j].x, boundsQuad[j].y]));
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
//屏蔽有偏移性质的style属性,偏移量在算bounds时已经加入计算
|
|
301
|
+
var bounds = new Bounds(geoBs[3][0], geoBs[3][1], geoBs[1][0], [geoBs[1][1]]);
|
|
302
|
+
var center = bounds.getCenterLonLat();
|
|
303
|
+
var label = new GeoText(center.lon, center.lat, fi.attributes[this.themeField]);
|
|
304
|
+
label.calculateBounds();
|
|
305
|
+
styTmp = CommonUtil.cloneObject(fi.style);
|
|
306
|
+
feaSty = CommonUtil.cloneObject(CommonUtil.copyAttributes(styTmp, styleTemp));
|
|
307
|
+
fea = new FeatureVector(label, fi.attributes, feaSty);
|
|
308
|
+
//赋予id
|
|
309
|
+
fea.id = fi.id;
|
|
310
|
+
fea.fid = fi.fid;
|
|
311
|
+
feas.push(fea);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
//返回最终要绘制的标签要素
|
|
316
|
+
return feas;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* @function Label.prototype.getStyleByData
|
|
321
|
+
* @description 根据用户数据(feature)设置专题要素的 Style。
|
|
322
|
+
* @param {FeatureVector} feat - 矢量要素对象。
|
|
323
|
+
* @returns {Array.<ThemeStyle>} 专题要素的 Style。
|
|
324
|
+
*/
|
|
325
|
+
getStyleByData(feat) {
|
|
326
|
+
var feature = feat;
|
|
327
|
+
feature.style = CommonUtil.copyAttributes(feature.style, this.defaultStyle);
|
|
328
|
+
//将style赋给标签
|
|
329
|
+
if (this.style && this.style.fontSize && parseFloat(this.style.fontSize) < 12) {
|
|
330
|
+
this.style.fontSize = "12px";
|
|
331
|
+
}
|
|
332
|
+
feature.style = CommonUtil.copyAttributes(feature.style, this.style);
|
|
333
|
+
|
|
334
|
+
if (this.themeField && this.styleGroups && feature.attributes) {
|
|
335
|
+
var Sf = this.themeField;
|
|
336
|
+
var attributes = feature.attributes;
|
|
337
|
+
var groups = this.styleGroups;
|
|
338
|
+
var isSfInAttrs = false; //指定的 groupField 是否是geotext的属性字段之一
|
|
339
|
+
var attr = null; //属性值
|
|
340
|
+
|
|
341
|
+
for (var property in attributes) {
|
|
342
|
+
if (Sf === property) {
|
|
343
|
+
isSfInAttrs = true;
|
|
344
|
+
attr = attributes[property];
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
//判断属性值是否属于styleGroups的某一个范围,以便对标签分组
|
|
350
|
+
if (isSfInAttrs) {
|
|
351
|
+
for (var i = 0, len = groups.length; i < len; i++) {
|
|
352
|
+
if ((attr >= groups[i].start) && (attr < groups[i].end)) {
|
|
353
|
+
var sty1 = groups[i].style;
|
|
354
|
+
if (sty1 && sty1.fontSize && parseFloat(sty1.fontSize) < 12) {
|
|
355
|
+
sty1.fontSize = "12px";
|
|
356
|
+
}
|
|
357
|
+
feature.style = CommonUtil.copyAttributes(feature.style, sty1);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
feature.style.label = feature.attributes[this.themeField]
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
return feature.style;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* @function Label.prototype.setLabelsStyle
|
|
370
|
+
* @description 设置标签要素的 Style。
|
|
371
|
+
* @param {Array.<FeatureVector>} labelFeatures - 需要设置 Style 的标签要素数组。
|
|
372
|
+
* @returns {Array.<FeatureVector>} 赋予 Style 后的标签要素数组。
|
|
373
|
+
*/
|
|
374
|
+
setLabelsStyle(labelFeatures) {
|
|
375
|
+
var fea, labelFeas = [];
|
|
376
|
+
for (var i = 0, len = labelFeatures.length; i < len; i++) {
|
|
377
|
+
var feature = labelFeatures[i];
|
|
378
|
+
if (feature.geometry.CLASS_NAME === "SuperMap.Geometry.GeoText") {
|
|
379
|
+
//设置标签的Style
|
|
380
|
+
if (feature.geometry.bsInfo.w || feature.geometry.bsInfo.h) {
|
|
381
|
+
feature.geometry.bsInfo.w = null;
|
|
382
|
+
feature.geometry.bsInfo.h = null;
|
|
383
|
+
feature.geometry.labelWTmp = null;
|
|
384
|
+
}
|
|
385
|
+
fea = this.setStyle(feature);
|
|
386
|
+
//为标签要素指定图层
|
|
387
|
+
fea.layer = this.layer;
|
|
388
|
+
labelFeas.push(fea);
|
|
389
|
+
} else {
|
|
390
|
+
return labelFeatures;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return labelFeas;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* @function Label.prototype.setStyle
|
|
398
|
+
* @description 设置标签要素的 Style。
|
|
399
|
+
* @param {FeatureVector} feat - 需要赋予 style 的要素。
|
|
400
|
+
*/
|
|
401
|
+
setStyle(feat) {
|
|
402
|
+
var feature = feat;
|
|
403
|
+
feature.style = CommonUtil.copyAttributes(feature.style, this.defaultStyle);
|
|
404
|
+
//将style赋给标签
|
|
405
|
+
if (this.style && this.style.fontSize && parseFloat(this.style.fontSize) < 12) {
|
|
406
|
+
this.style.fontSize = "12px";
|
|
407
|
+
}
|
|
408
|
+
feature.style = CommonUtil.copyAttributes(feature.style, this.style);
|
|
409
|
+
|
|
410
|
+
if (this.groupField && this.styleGroups && feature.attributes) {
|
|
411
|
+
var Sf = this.groupField;
|
|
412
|
+
var attributes = feature.attributes;
|
|
413
|
+
var groups = this.styleGroups;
|
|
414
|
+
var isSfInAttrs = false; //指定的 groupField 是否是geotext的属性字段之一
|
|
415
|
+
var attr = null; //属性值
|
|
416
|
+
|
|
417
|
+
for (var property in attributes) {
|
|
418
|
+
if (Sf === property) {
|
|
419
|
+
isSfInAttrs = true;
|
|
420
|
+
attr = attributes[property];
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
//判断属性值是否属于styleGroups的某一个范围,以便对标签分组
|
|
426
|
+
if (isSfInAttrs) {
|
|
427
|
+
for (var i = 0, len = groups.length; i < len; i++) {
|
|
428
|
+
if ((attr >= groups[i].start) && (attr < groups[i].end)) {
|
|
429
|
+
var sty1 = groups[i].style;
|
|
430
|
+
if (sty1 && sty1.fontSize && parseFloat(sty1.fontSize) < 12) {
|
|
431
|
+
sty1.fontSize = "12px";
|
|
432
|
+
}
|
|
433
|
+
feature.style = CommonUtil.copyAttributes(feature.style, sty1);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
//将文本内容赋到标签要素的style上
|
|
440
|
+
feature.style.label = feature.geometry.text;
|
|
441
|
+
|
|
442
|
+
return feature;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* @function Label.prototype.getLabelPxLocation
|
|
447
|
+
* @description 获取标签要素的像素坐标。
|
|
448
|
+
* @param {FeatureVector} feature - 标签要素。
|
|
449
|
+
* @returns {Object} 标签位置,例如:{"x":1,"y":1}。
|
|
450
|
+
*/
|
|
451
|
+
getLabelPxLocation(feature) {
|
|
452
|
+
var geoText = feature.geometry;
|
|
453
|
+
var styleTmp = feature.style;
|
|
454
|
+
|
|
455
|
+
//将标签的地理位置转为像素位置
|
|
456
|
+
var locationTmp = geoText.getCentroid();
|
|
457
|
+
var locTmp = this.map.getPixelFromCoordinate([locationTmp.x, locationTmp.y]);
|
|
458
|
+
var loc = new Point([locTmp[0], locTmp[1]]);
|
|
459
|
+
|
|
460
|
+
//偏移处理
|
|
461
|
+
if (styleTmp.labelXOffset || styleTmp.labelYOffset) {
|
|
462
|
+
var xOffset = isNaN(styleTmp.labelXOffset) ? 0 : styleTmp.labelXOffset;
|
|
463
|
+
var yOffset = isNaN(styleTmp.labelYOffset) ? 0 : styleTmp.labelYOffset;
|
|
464
|
+
loc.translate(xOffset, -yOffset);
|
|
465
|
+
}
|
|
466
|
+
return {
|
|
467
|
+
x: loc.getCoordinates()[0],
|
|
468
|
+
y: loc.getCoordinates()[1]
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* @function Label.prototype.calculateLabelBounds
|
|
475
|
+
* @description 获得标签要素的最终范围。
|
|
476
|
+
* @param {FeatureVector} feature - 需要计算bounds的标签要素数。
|
|
477
|
+
* @param {Object} loc - 标签位置,例如:{"x":1,"y":1}。
|
|
478
|
+
* @returns {Array.<Object>} 四边形节点数组。例如:[{"x":1,"y":1},{"x":3,"y":1},{"x":6,"y":4},{"x":2,"y":10},{"x":1,"y":1}]。
|
|
479
|
+
*/
|
|
480
|
+
calculateLabelBounds(feature, loc) {
|
|
481
|
+
var geoText = feature.geometry;
|
|
482
|
+
|
|
483
|
+
//标签范围(未旋转前)
|
|
484
|
+
var labB = null;
|
|
485
|
+
var labelInfo = null;
|
|
486
|
+
//获取bounds的方式
|
|
487
|
+
if (this.getPxBoundsMode == 0) {
|
|
488
|
+
labB = geoText.getLabelPxBoundsByText(loc, feature.style);
|
|
489
|
+
} else if (this.getPxBoundsMode === 1) {
|
|
490
|
+
//canvas
|
|
491
|
+
labelInfo = this.getLabelInfo(feature.geometry.getCentroid(), feature.style);
|
|
492
|
+
labB = geoText.getLabelPxBoundsByLabel(loc, labelInfo.w, labelInfo.h, feature.style);
|
|
493
|
+
} else {
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
//旋转Bounds
|
|
498
|
+
var boundsQuad = [];
|
|
499
|
+
if ((feature.style.labelRotation % 180) == 0) {
|
|
500
|
+
boundsQuad = [{
|
|
501
|
+
"x": labB.left,
|
|
502
|
+
"y": labB.top
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
"x": labB.right,
|
|
506
|
+
"y": labB.top
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
"x": labB.right,
|
|
510
|
+
"y": labB.bottom
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
"x": labB.left,
|
|
514
|
+
"y": labB.bottom
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
"x": labB.left,
|
|
518
|
+
"y": labB.top
|
|
519
|
+
}
|
|
520
|
+
];
|
|
521
|
+
} else {
|
|
522
|
+
boundsQuad = this.rotationBounds(labB, loc, feature.style.labelRotation);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
//重置GeoText的bounds
|
|
526
|
+
geoText.bounds = new Bounds(boundsQuad[1].x, boundsQuad[3].y, boundsQuad[2].x, boundsQuad[4].y);
|
|
527
|
+
return boundsQuad;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* @function Label.prototype.calculateLabelBounds2
|
|
532
|
+
* @description 获得标签要素的最终范围的另一种算法(通过记录下的标签宽高),提高计算 bounds 的效率。
|
|
533
|
+
* @param {FeatureVector} feature - 需要计算 bounds 的标签要素数。
|
|
534
|
+
* @param {Object} loc - 标签位置,例如:{"x":1,"y":1}。
|
|
535
|
+
* @returns {Array.<Object>} 四边形节点数组。例如:[{"x":1,"y":1},{"x":3,"y":1},{"x":6,"y":4},{"x":2,"y":10},{"x":1,"y":1}]。
|
|
536
|
+
*/
|
|
537
|
+
calculateLabelBounds2(feature, loc) {
|
|
538
|
+
var labB, left, bottom, top, right;
|
|
539
|
+
var labelSize = feature.geometry.bsInfo;
|
|
540
|
+
var style = feature.style;
|
|
541
|
+
var locationPx = CommonUtil.cloneObject(loc);
|
|
542
|
+
|
|
543
|
+
//处理文字对齐
|
|
544
|
+
if (style.labelAlign && style.labelAlign !== "cm") {
|
|
545
|
+
switch (style.labelAlign) {
|
|
546
|
+
case "lt":
|
|
547
|
+
locationPx.x += labelSize.w / 2;
|
|
548
|
+
locationPx.y += labelSize.h / 2;
|
|
549
|
+
break;
|
|
550
|
+
case "lm":
|
|
551
|
+
locationPx.x += labelSize.w / 2;
|
|
552
|
+
break;
|
|
553
|
+
case "lb":
|
|
554
|
+
locationPx.x += labelSize.w / 2;
|
|
555
|
+
locationPx.y -= labelSize.h / 2;
|
|
556
|
+
break;
|
|
557
|
+
case "ct":
|
|
558
|
+
locationPx.y += labelSize.h / 2;
|
|
559
|
+
break;
|
|
560
|
+
case "cb":
|
|
561
|
+
locationPx.y -= labelSize.h / 2;
|
|
562
|
+
break;
|
|
563
|
+
case "rt":
|
|
564
|
+
locationPx.x -= labelSize.w / 2;
|
|
565
|
+
locationPx.y += labelSize.h / 2;
|
|
566
|
+
break;
|
|
567
|
+
case "rm":
|
|
568
|
+
locationPx.x -= labelSize.w / 2;
|
|
569
|
+
break;
|
|
570
|
+
case "rb":
|
|
571
|
+
locationPx.x -= labelSize.w / 2;
|
|
572
|
+
locationPx.y -= labelSize.h / 2;
|
|
573
|
+
break;
|
|
574
|
+
default:
|
|
575
|
+
break;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
left = locationPx.x - labelSize.w / 2;
|
|
580
|
+
bottom = locationPx.y + labelSize.h / 2;
|
|
581
|
+
//处理斜体字
|
|
582
|
+
if (style.fontStyle && style.fontStyle === "italic") {
|
|
583
|
+
right = locationPx.x + labelSize.w / 2 + parseInt(parseFloat(style.fontSize) / 2);
|
|
584
|
+
} else {
|
|
585
|
+
right = locationPx.x + labelSize.w / 2;
|
|
586
|
+
}
|
|
587
|
+
top = locationPx.y - labelSize.h / 2;
|
|
588
|
+
|
|
589
|
+
labB = new Bounds(left, bottom, right, top);
|
|
590
|
+
|
|
591
|
+
//旋转Bounds
|
|
592
|
+
var boundsQuad = [];
|
|
593
|
+
if ((style.labelRotation % 180) == 0) {
|
|
594
|
+
boundsQuad = [{
|
|
595
|
+
"x": labB.left,
|
|
596
|
+
"y": labB.top
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
"x": labB.right,
|
|
600
|
+
"y": labB.top
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
"x": labB.right,
|
|
604
|
+
"y": labB.bottom
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
"x": labB.left,
|
|
608
|
+
"y": labB.bottom
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
"x": labB.left,
|
|
612
|
+
"y": labB.top
|
|
613
|
+
}
|
|
614
|
+
];
|
|
615
|
+
} else {
|
|
616
|
+
boundsQuad = this.rotationBounds(labB, loc, style.labelRotation);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
//重置GeoText的bounds
|
|
620
|
+
feature.geometry.bounds = new Bounds(boundsQuad[1].x, boundsQuad[3].y, boundsQuad[2].x, boundsQuad[4].y);
|
|
621
|
+
return boundsQuad;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* @function Label.prototype.getLabelInfo
|
|
626
|
+
* @description 根据当前位置获取绘制后的标签信息,包括标签的宽,高和行数等。
|
|
627
|
+
* @returns {Object} 绘制后的标签信息。
|
|
628
|
+
*/
|
|
629
|
+
getLabelInfo(location, style) {
|
|
630
|
+
var LABEL_ALIGN = {
|
|
631
|
+
"l": "left",
|
|
632
|
+
"r": "right",
|
|
633
|
+
"t": "top",
|
|
634
|
+
"b": "bottom"
|
|
635
|
+
},
|
|
636
|
+
LABEL_FACTOR = {
|
|
637
|
+
"l": 0,
|
|
638
|
+
"r": -1,
|
|
639
|
+
"t": 0,
|
|
640
|
+
"b": -1
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
style = CommonUtil.extend({
|
|
644
|
+
fontColor: "#000000",
|
|
645
|
+
labelAlign: "cm"
|
|
646
|
+
}, style);
|
|
647
|
+
var pt = this.getLocalXY(location);
|
|
648
|
+
var labelWidth = 0;
|
|
649
|
+
|
|
650
|
+
if (style.labelXOffset || style.labelYOffset) {
|
|
651
|
+
var xOffset = isNaN(style.labelXOffset) ? 0 : style.labelXOffset;
|
|
652
|
+
var yOffset = isNaN(style.labelYOffset) ? 0 : style.labelYOffset;
|
|
653
|
+
pt[0] += xOffset;
|
|
654
|
+
pt[1] -= yOffset;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
var canvas = document.createElement('canvas');
|
|
658
|
+
canvas.globalAlpha = 0;
|
|
659
|
+
canvas.lineWidth = 1;
|
|
660
|
+
|
|
661
|
+
var ctx = canvas.getContext("2d");
|
|
662
|
+
|
|
663
|
+
ctx.fillStyle = style.fontColor;
|
|
664
|
+
ctx.globalAlpha = style.fontOpacity || 1.0;
|
|
665
|
+
var fontStyle = [style.fontStyle ? style.fontStyle : "normal",
|
|
666
|
+
"normal",
|
|
667
|
+
style.fontWeight ? style.fontWeight : "normal",
|
|
668
|
+
style.fontSize ? style.fontSize : "1em",
|
|
669
|
+
style.fontFamily ? style.fontFamily : "sans-serif"
|
|
670
|
+
].join(" ");
|
|
671
|
+
var labelRows = style.label.split('\n');
|
|
672
|
+
var numRows = labelRows.length;
|
|
673
|
+
var vfactor, lineHeight, labelWidthTmp;
|
|
674
|
+
if (ctx.fillText) {
|
|
675
|
+
// HTML5
|
|
676
|
+
ctx.font = fontStyle;
|
|
677
|
+
ctx.textAlign = LABEL_ALIGN[style.labelAlign[0]] ||
|
|
678
|
+
"center";
|
|
679
|
+
ctx.textBaseline = LABEL_ALIGN[style.labelAlign[1]] ||
|
|
680
|
+
"middle";
|
|
681
|
+
vfactor = LABEL_FACTOR[style.labelAlign[1]];
|
|
682
|
+
if (vfactor == null) {
|
|
683
|
+
vfactor = -.5;
|
|
684
|
+
}
|
|
685
|
+
lineHeight = ctx.measureText('Mg').height ||
|
|
686
|
+
ctx.measureText('xx').width;
|
|
687
|
+
pt[1] += lineHeight * vfactor * (numRows - 1);
|
|
688
|
+
for (let i = 0; i < numRows; i++) {
|
|
689
|
+
labelWidthTmp = ctx.measureText(labelRows[i]).width;
|
|
690
|
+
if (labelWidth < labelWidthTmp) {
|
|
691
|
+
labelWidth = labelWidthTmp;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
} else if (ctx.mozDrawText) {
|
|
695
|
+
// Mozilla pre-Gecko1.9.1 (<FF3.1)
|
|
696
|
+
ctx.mozTextStyle = fontStyle;
|
|
697
|
+
vfactor = LABEL_FACTOR[style.labelAlign[1]];
|
|
698
|
+
if (vfactor == null) {
|
|
699
|
+
vfactor = -.5;
|
|
700
|
+
}
|
|
701
|
+
lineHeight = ctx.mozMeasureText('xx');
|
|
702
|
+
pt[1] += lineHeight * (1 + (vfactor * numRows));
|
|
703
|
+
for (let i = 0; i < numRows; i++) {
|
|
704
|
+
labelWidthTmp = ctx.measureText(labelRows[i]).width;
|
|
705
|
+
if (labelWidth < labelWidthTmp) {
|
|
706
|
+
labelWidth = labelWidthTmp;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
var labelInfo = {}; //标签信息
|
|
711
|
+
if (labelWidth) {
|
|
712
|
+
labelInfo.w = labelWidth; //标签的宽
|
|
713
|
+
} else {
|
|
714
|
+
return null;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
labelInfo.h = style.fontSize; //一行标签的高
|
|
718
|
+
labelInfo.rows = labelRows.length; //标签的行数
|
|
719
|
+
|
|
720
|
+
return labelInfo;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* @function Label.prototype.rotationBounds
|
|
725
|
+
* @description 旋转 bounds。
|
|
726
|
+
* @param {Bounds} bounds - 要旋转的 bounds。
|
|
727
|
+
* @param {Object} rotationCenterPoi - 旋转中心点对象,此对象含有属性 x(横坐标),属性 y(纵坐标)。
|
|
728
|
+
* @param {number} angle - 旋转角度(顺时针)。
|
|
729
|
+
* @returns {Array.<Object>} bounds 旋转后形成的多边形节点数组。是一个四边形,形如:[{"x":1,"y":1},{"x":3,"y":1},{"x":6,"y":4},{"x":2,"y":10},{"x":1,"y":1}]。
|
|
730
|
+
*/
|
|
731
|
+
rotationBounds(bounds, rotationCenterPoi, angle) {
|
|
732
|
+
var ltPoi = new Point([bounds.left, bounds.top]);
|
|
733
|
+
var rtPoi = new Point([bounds.right, bounds.top]);
|
|
734
|
+
var rbPoi = new Point([bounds.right, bounds.bottom]);
|
|
735
|
+
var lbPoi = new Point([bounds.left, bounds.bottom]);
|
|
736
|
+
|
|
737
|
+
var ver = [];
|
|
738
|
+
ver.push(this.getRotatedLocation(ltPoi.getCoordinates()[0], ltPoi.getCoordinates()[1], rotationCenterPoi.x, rotationCenterPoi.y, angle));
|
|
739
|
+
ver.push(this.getRotatedLocation(rtPoi.getCoordinates()[0], rtPoi.getCoordinates()[1], rotationCenterPoi.x, rotationCenterPoi.y, angle));
|
|
740
|
+
ver.push(this.getRotatedLocation(rbPoi.getCoordinates()[0], rbPoi.getCoordinates()[1], rotationCenterPoi.x, rotationCenterPoi.y, angle));
|
|
741
|
+
ver.push(this.getRotatedLocation(lbPoi.getCoordinates()[0], lbPoi.getCoordinates()[1], rotationCenterPoi.x, rotationCenterPoi.y, angle));
|
|
742
|
+
|
|
743
|
+
//bounds旋转后形成的多边形节点数组
|
|
744
|
+
var quad = [];
|
|
745
|
+
|
|
746
|
+
for (var i = 0; i < ver.length; i++) {
|
|
747
|
+
quad.push({
|
|
748
|
+
"x": ver[i].x,
|
|
749
|
+
"y": ver[i].y
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
quad.push({
|
|
753
|
+
"x": ver[0].x,
|
|
754
|
+
"y": ver[0].y
|
|
755
|
+
});
|
|
756
|
+
return quad;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* @function Label.prototype.getRotatedLocation
|
|
761
|
+
* @description 获取一个点绕旋转中心顺时针旋转后的位置。(此方法用于屏幕坐标)。
|
|
762
|
+
* @param {number} x - 旋转点横坐标。
|
|
763
|
+
* @param {number} y - 旋转点纵坐标。
|
|
764
|
+
* @param {number} rx - 旋转中心点横坐标。
|
|
765
|
+
* @param {number} ry - 旋转中心点纵坐标。
|
|
766
|
+
* @param {number} angle - 旋转角度
|
|
767
|
+
* @returns {Object} 旋转后的坐标位置对象,该对象含有属性 x(横坐标),属性 y(纵坐标)。
|
|
768
|
+
*/
|
|
769
|
+
getRotatedLocation(x, y, rx, ry, angle) {
|
|
770
|
+
var loc = {},
|
|
771
|
+
x0, y0;
|
|
772
|
+
|
|
773
|
+
y = -y;
|
|
774
|
+
ry = -ry;
|
|
775
|
+
angle = -angle; //顺时针旋转
|
|
776
|
+
x0 = (x - rx) * Math.cos((angle / 180) * Math.PI) - (y - ry) * Math.sin((angle / 180) * Math.PI) + rx;
|
|
777
|
+
y0 = (x - rx) * Math.sin((angle / 180) * Math.PI) + (y - ry) * Math.cos((angle / 180) * Math.PI) + ry;
|
|
778
|
+
|
|
779
|
+
loc.x = x0;
|
|
780
|
+
loc.y = -y0;
|
|
781
|
+
|
|
782
|
+
return loc;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* @function Label.prototype.getAvoidInfo
|
|
787
|
+
* @description 获取避让的信息。
|
|
788
|
+
* @param {Bounds} bounds - 地图像素范围。
|
|
789
|
+
* @param {Array.<Object>} quadrilateral - 四边形节点数组。例如:[{"x":1,"y":1},{"x":3,"y":1},{"x":6,"y":4},{"x":2,"y":10},{"x":1,"y":1}]。
|
|
790
|
+
* @returns {Object} 避让的信息。
|
|
791
|
+
*/
|
|
792
|
+
getAvoidInfo(bounds, quadrilateral) {
|
|
793
|
+
if (quadrilateral.length !== 5) {
|
|
794
|
+
return null;
|
|
795
|
+
} //不是四边形
|
|
796
|
+
|
|
797
|
+
//将bound序列化为点数组形式
|
|
798
|
+
var bounddQuad = [{
|
|
799
|
+
"x": bounds.left,
|
|
800
|
+
"y": bounds.top
|
|
801
|
+
},
|
|
802
|
+
{
|
|
803
|
+
"x": bounds.right,
|
|
804
|
+
"y": bounds.top
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
"x": bounds.right,
|
|
808
|
+
"y": bounds.bottom
|
|
809
|
+
},
|
|
810
|
+
{
|
|
811
|
+
"x": bounds.left,
|
|
812
|
+
"y": bounds.bottom
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
"x": bounds.left,
|
|
816
|
+
"y": bounds.top
|
|
817
|
+
}
|
|
818
|
+
];
|
|
819
|
+
|
|
820
|
+
var isIntersection = false,
|
|
821
|
+
bqLen = bounddQuad.length,
|
|
822
|
+
quadLen = quadrilateral.length;
|
|
823
|
+
|
|
824
|
+
var offsetX = 0,
|
|
825
|
+
offsetY = 0,
|
|
826
|
+
aspectH = "",
|
|
827
|
+
aspectW = "";
|
|
828
|
+
for (var i = 0; i < bqLen - 1; i++) {
|
|
829
|
+
for (var j = 0; j < quadLen - 1; j++) {
|
|
830
|
+
var isLineIn = CommonUtil.lineIntersection(bounddQuad[i], bounddQuad[i + 1], quadrilateral[j], quadrilateral[j + 1]);
|
|
831
|
+
if (isLineIn.CLASS_NAME === "SuperMap.Geometry.Point") {
|
|
832
|
+
//设置避让信息
|
|
833
|
+
setInfo(quadrilateral[j]);
|
|
834
|
+
setInfo(quadrilateral[j + 1]);
|
|
835
|
+
isIntersection = true;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if (isIntersection) {
|
|
841
|
+
//组织避让操作所需的信息
|
|
842
|
+
return {
|
|
843
|
+
"aspectW": aspectW,
|
|
844
|
+
"aspectH": aspectH,
|
|
845
|
+
"offsetX": offsetX,
|
|
846
|
+
"offsetY": offsetY
|
|
847
|
+
};
|
|
848
|
+
} else {
|
|
849
|
+
return null;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
//内部函数:设置避让信息
|
|
854
|
+
//参数:vec-{Object} quadrilateral四边形单个节点。如:{"x":1,"y":1}。
|
|
855
|
+
function setInfo(vec) {
|
|
856
|
+
//四边形不在bounds内的节点
|
|
857
|
+
if (!bounds.contains(vec.x, vec.y)) {
|
|
858
|
+
//bounds的Top边
|
|
859
|
+
if (vec.y < bounds.top) {
|
|
860
|
+
let oY = Math.abs(bounds.top - vec.y);
|
|
861
|
+
if (oY > offsetY) {
|
|
862
|
+
offsetY = oY;
|
|
863
|
+
aspectH = "top";
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
//bounds的Bottom边
|
|
868
|
+
if (vec.y > bounds.bottom) {
|
|
869
|
+
let oY = Math.abs(vec.y - bounds.bottom);
|
|
870
|
+
if (oY > offsetY) {
|
|
871
|
+
offsetY = oY;
|
|
872
|
+
aspectH = "bottom";
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
//bounds的left边
|
|
877
|
+
if (vec.x < bounds.left) {
|
|
878
|
+
let oX = Math.abs(bounds.left - vec.x);
|
|
879
|
+
if (oX > offsetX) {
|
|
880
|
+
offsetX = oX;
|
|
881
|
+
aspectW = "left";
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
//bounds的right边
|
|
886
|
+
if (vec.x > bounds.right) {
|
|
887
|
+
let oX = Math.abs(vec.x - bounds.right);
|
|
888
|
+
if (oX > offsetX) {
|
|
889
|
+
offsetX = oX;
|
|
890
|
+
aspectW = "right";
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* @function Label.prototype.isQuadrilateralOverLap
|
|
901
|
+
* @description 判断两个四边形是否有压盖。
|
|
902
|
+
* @param {Array.<Object>} quadrilateral - 四边形节点数组。例如:[{"x":1,"y":1},{"x":3,"y":1},{"x":6,"y":4},{"x":2,"y":10},{"x":1,"y":1}]。
|
|
903
|
+
* @param {Array.<Object>} quadrilateral2 - 第二个四边形节点数组。
|
|
904
|
+
* @returns {boolean} 是否压盖,true 表示压盖。
|
|
905
|
+
*/
|
|
906
|
+
isQuadrilateralOverLap(quadrilateral, quadrilateral2) {
|
|
907
|
+
var quadLen = quadrilateral.length,
|
|
908
|
+
quad2Len = quadrilateral2.length;
|
|
909
|
+
if (quadLen !== 5 || quad2Len !== 5) {
|
|
910
|
+
return null;
|
|
911
|
+
} //不是四边形
|
|
912
|
+
|
|
913
|
+
var OverLap = false;
|
|
914
|
+
//如果两四边形互不包含对方的节点,则两个四边形不相交
|
|
915
|
+
for (let i = 0; i < quadLen; i++) {
|
|
916
|
+
if (this.isPointInPoly(quadrilateral[i], quadrilateral2)) {
|
|
917
|
+
OverLap = true;
|
|
918
|
+
break;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
for (let i = 0; i < quad2Len; i++) {
|
|
922
|
+
if (this.isPointInPoly(quadrilateral2[i], quadrilateral)) {
|
|
923
|
+
OverLap = true;
|
|
924
|
+
break;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
//加上两矩形十字相交的情况
|
|
928
|
+
for (let i = 0; i < quadLen - 1; i++) {
|
|
929
|
+
if (OverLap) {
|
|
930
|
+
break;
|
|
931
|
+
}
|
|
932
|
+
for (var j = 0; j < quad2Len - 1; j++) {
|
|
933
|
+
var isLineIn = CommonUtil.lineIntersection(quadrilateral[i], quadrilateral[i + 1], quadrilateral2[j], quadrilateral2[j + 1]);
|
|
934
|
+
if (isLineIn.CLASS_NAME === "SuperMap.Geometry.Point") {
|
|
935
|
+
OverLap = true;
|
|
936
|
+
break;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
return OverLap;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/**
|
|
945
|
+
* @function Label.prototype.isPointInPoly
|
|
946
|
+
* @description 判断一个点是否在多边形里面(射线法)。
|
|
947
|
+
* @param {Object} pt - 需要判定的点对象,该对象含有属性 x(横坐标),属性 y(纵坐标)。
|
|
948
|
+
* @param {Array.<Object>} poly - 多边形节点数组。例如一个四边形:[{"x":1,"y":1},{"x":3,"y":1},{"x":6,"y":4},{"x":2,"y":10},{"x":1,"y":1}]。
|
|
949
|
+
* @returns {boolean} 点是否在多边形内。
|
|
950
|
+
*/
|
|
951
|
+
isPointInPoly(pt, poly) {
|
|
952
|
+
for (var isIn = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) {
|
|
953
|
+
((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) &&
|
|
954
|
+
(pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) &&
|
|
955
|
+
(isIn = !isIn);
|
|
956
|
+
}
|
|
957
|
+
return isIn;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
canvasFunctionInternal_(extent, resolution, pixelRatio, size, projection) { // eslint-disable-line no-unused-vars
|
|
962
|
+
return super.canvasFunctionInternal_.apply(this, arguments);
|
|
963
|
+
}
|
|
964
|
+
}
|