cd-mapgis 1.1.31 → 1.1.32
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/package.json +1 -1
- package/src/DataLayer.js +129 -0
- package/src/StyleUtil.js +95 -0
package/package.json
CHANGED
package/src/DataLayer.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import GeoJSON from 'ol/format/GeoJSON.js';
|
|
2
|
+
import Feature from 'ol/Feature.js';
|
|
3
|
+
import LineString from 'ol/geom/LineString.js';
|
|
4
|
+
import Polygon from 'ol/geom/Polygon.js';
|
|
5
|
+
import Point from 'ol/geom/Point.js';
|
|
6
|
+
import StyleUtil from './StyleUtil.js';
|
|
7
|
+
import MapView from './MapView.js';
|
|
8
|
+
import VectorSource from 'ol/source/Vector.js';
|
|
9
|
+
import VectorLayer from 'ol/layer/Vector.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 自定义数据图层 {mapView,style:样式,click:点击回调,dataType:geometry|geoJson|LinePoints|PolygonPoints|point}
|
|
13
|
+
*/
|
|
14
|
+
export default class DataLayer {
|
|
15
|
+
constructor(p) {
|
|
16
|
+
this.vectorSource = new VectorSource();
|
|
17
|
+
this.vectorLayer = new VectorLayer({
|
|
18
|
+
source: this.vectorSource
|
|
19
|
+
});
|
|
20
|
+
this.mapView = p.mapView ? p.mapView : MapView.Instance;
|
|
21
|
+
this.map = this.mapView.map;
|
|
22
|
+
this.map.addLayer(this.vectorLayer);
|
|
23
|
+
this.geoJSON = new GeoJSON();
|
|
24
|
+
// 存储点击回调函数(可选,支持多个回调时可用数组)
|
|
25
|
+
this.clickCallbacks = [];
|
|
26
|
+
// 绑定地图点击事件
|
|
27
|
+
this.map.on('click', (evt) => this._handleMapClick(evt));
|
|
28
|
+
//点击事件
|
|
29
|
+
if (p.click) this.clickCallbacks.push(p.click);
|
|
30
|
+
//默认样式
|
|
31
|
+
this.style = p.style;
|
|
32
|
+
//数据格式
|
|
33
|
+
this.dataType = p.dataType ? p.dataType : 'geometry';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//添加数据
|
|
37
|
+
add(p) {
|
|
38
|
+
if (Array.isArray(p)) {
|
|
39
|
+
let a = [];
|
|
40
|
+
for (let i = 0; i < p.length; i++) {
|
|
41
|
+
a.push(this._getFeature(p[i]));
|
|
42
|
+
}
|
|
43
|
+
this.vectorSource.addFeatures(a);
|
|
44
|
+
} else {
|
|
45
|
+
this.vectorSource.addFeature(this._getFeature(p));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 缩放到本图层显示范围
|
|
51
|
+
*/
|
|
52
|
+
fitToLayer(p) {
|
|
53
|
+
const map = this.map;
|
|
54
|
+
let view = map.getView();
|
|
55
|
+
let ext = this.vectorSource.getExtent();
|
|
56
|
+
if (!ext) {
|
|
57
|
+
console.error("没有获取到图层范围");
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (!p || !p.zoom) {
|
|
61
|
+
view.fit(ext, {
|
|
62
|
+
size: map.getSize(),
|
|
63
|
+
maxZoom: 18
|
|
64
|
+
})
|
|
65
|
+
} else {
|
|
66
|
+
view.setCenter([(ext[0] + ext[2]) / 2.0, (ext[1] + ext[3]) / 2.0]);
|
|
67
|
+
view.setZoom(p.zoom);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 注册点要素的点击事件处理器
|
|
73
|
+
* @param {Function} callback - 回调函数,接收参数 (feature, event)
|
|
74
|
+
*/
|
|
75
|
+
onClick(callback) {
|
|
76
|
+
if (typeof callback === 'function') {
|
|
77
|
+
this.clickCallbacks.push(callback);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//根据数据获取单个要素 {data:几何数据,style:样式,dataType,}
|
|
82
|
+
_getFeature(p) {
|
|
83
|
+
let dataType = p.dataType ? p.dataType : this.dataType;
|
|
84
|
+
let style = p.style ? p.style : this.style;
|
|
85
|
+
let feature;
|
|
86
|
+
if (dataType == 'geoJson') {
|
|
87
|
+
feature = this.geoJSON.readFeature(p.data);
|
|
88
|
+
} else if (dataType == 'geometry') {
|
|
89
|
+
let geometry = this.geoJSON.readGeometry(p.data);
|
|
90
|
+
feature = new Feature({ geometry: geometry });
|
|
91
|
+
} else if (dataType == 'LinePoints') {
|
|
92
|
+
feature = new Feature({
|
|
93
|
+
geometry: new LineString(p.data)
|
|
94
|
+
});
|
|
95
|
+
} else if (dataType == 'PolygonPoints') {
|
|
96
|
+
feature = new Feature({
|
|
97
|
+
geometry: new Polygon(p.data)
|
|
98
|
+
});
|
|
99
|
+
} else if (dataType == 'point') {
|
|
100
|
+
feature = new Feature({
|
|
101
|
+
geometry: new Point(p.data)
|
|
102
|
+
});
|
|
103
|
+
} else {
|
|
104
|
+
console.error("不支持的数据类型:" + dataType);
|
|
105
|
+
}
|
|
106
|
+
feature.setStyle(StyleUtil.getStyle(feature.getGeometry().getType(), style));
|
|
107
|
+
feature.set('attr', p.attr);
|
|
108
|
+
return feature;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 处理地图点击事件
|
|
113
|
+
* @private
|
|
114
|
+
*/
|
|
115
|
+
_handleMapClick(evt) {
|
|
116
|
+
const map = this.map;
|
|
117
|
+
const pixel = evt.pixel;
|
|
118
|
+
// 遍历点击位置的所有要素,只取第一个(或全部)
|
|
119
|
+
map.forEachFeatureAtPixel(pixel, (feature, layer) => {
|
|
120
|
+
// 只处理属于当前图层的要素,并且是点类型(可选)
|
|
121
|
+
if (layer === this.vectorLayer) {
|
|
122
|
+
// 触发所有已注册的回调
|
|
123
|
+
this.clickCallbacks.forEach(cb => cb(feature, evt));
|
|
124
|
+
}
|
|
125
|
+
// 返回 true 表示停止遍历(如果只想要第一个)
|
|
126
|
+
// 可根据需求决定是否停止
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
package/src/StyleUtil.js
CHANGED
|
@@ -207,4 +207,99 @@ export default class StyleUtil {
|
|
|
207
207
|
}
|
|
208
208
|
return new Style(styleParam);
|
|
209
209
|
}
|
|
210
|
+
|
|
211
|
+
//根据几何类型和样式配置获取样式
|
|
212
|
+
static getStyle(geoType, style0) {
|
|
213
|
+
let style = style0 ? style0 : {};
|
|
214
|
+
let styleParam = {};
|
|
215
|
+
switch (geoType) {
|
|
216
|
+
// 点 / 多点
|
|
217
|
+
case 'Point':
|
|
218
|
+
case 'MultiPoint':
|
|
219
|
+
styleParam.image = StyleUtil._getStyle_image(style);
|
|
220
|
+
styleParam.text = StyleUtil._getStyle_text(style);
|
|
221
|
+
break;
|
|
222
|
+
// 线 / 多线
|
|
223
|
+
case 'LineString':
|
|
224
|
+
case 'MultiLineString':
|
|
225
|
+
styleParam.stroke = StyleUtil._getStyle_stroke(style);
|
|
226
|
+
break;
|
|
227
|
+
// 面 / 多面 / 圆
|
|
228
|
+
case 'Polygon':
|
|
229
|
+
case 'MultiPolygon':
|
|
230
|
+
case 'Circle':
|
|
231
|
+
styleParam.stroke = StyleUtil._getStyle_stroke(style);
|
|
232
|
+
styleParam.fill = StyleUtil._getStyle_fill(style);
|
|
233
|
+
break;
|
|
234
|
+
default:
|
|
235
|
+
console.error("获取样式不支持的几何类型:" + geoType);
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
return new Style(styleParam);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
//获取图形样式
|
|
242
|
+
static _getStyle_image(style) {
|
|
243
|
+
if (style.img) {
|
|
244
|
+
return new Icon({
|
|
245
|
+
src: p.img, // 外部图标路径
|
|
246
|
+
scale: 1, // 缩放比例
|
|
247
|
+
anchor: [0.5, 0.5], // 锚点为中心
|
|
248
|
+
anchorOrigin: 'center',
|
|
249
|
+
anchorXUnits: 'fraction',
|
|
250
|
+
anchorYUnits: 'fraction'
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
return new Circle({
|
|
254
|
+
radius: 5,
|
|
255
|
+
stroke: new Stroke({
|
|
256
|
+
color: 'rgba(0, 0, 0, 0.7)'
|
|
257
|
+
}),
|
|
258
|
+
fill: new Fill({
|
|
259
|
+
color: 'rgba(255, 255, 255, 0.2)'
|
|
260
|
+
})
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
//获取标注文字样式
|
|
265
|
+
static _getStyle_text(style) {
|
|
266
|
+
if (style.text) {
|
|
267
|
+
let p = style.text;
|
|
268
|
+
let font = p.font ? p.font : 'bold 20px 宋体';
|
|
269
|
+
let color = p.color ? p.color : '#0619e9';
|
|
270
|
+
let offsetY = p.offsetY ? p.offsetY : -10;
|
|
271
|
+
let offsetX = p.offsetX ? p.offsetX : 0;
|
|
272
|
+
return new Text({
|
|
273
|
+
text: p.text, // 从要素属性获取文字
|
|
274
|
+
font: font,
|
|
275
|
+
overflow: true, // 关键设置:允许文字溢出
|
|
276
|
+
fill: new Fill({
|
|
277
|
+
color: color
|
|
278
|
+
}),
|
|
279
|
+
offsetX: offsetX,
|
|
280
|
+
offsetY: offsetY // 文字显示在图标上方
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
//获取笔画的样式(用于线或者区的外围边界线)
|
|
287
|
+
static _getStyle_stroke(style) {
|
|
288
|
+
let p = style.stroke ? style.stroke : {};
|
|
289
|
+
let color = p.color ? p.color : '#0af5e6';
|
|
290
|
+
let width = p.width ? p.width : 2;
|
|
291
|
+
return new Stroke({
|
|
292
|
+
color: color, // 默认选择色
|
|
293
|
+
width: width // 线宽
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
//获取填充样式
|
|
298
|
+
static _getStyle_fill(style) {
|
|
299
|
+
let p = style.fill ? style.fill : {};
|
|
300
|
+
let color = p.color ? p.color : 'rgba(255, 255, 255, 0.2)';
|
|
301
|
+
return new Fill({
|
|
302
|
+
color: color
|
|
303
|
+
});
|
|
304
|
+
}
|
|
210
305
|
}
|