my-openlayer 0.1.18 → 1.0.1

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.
@@ -1,10 +1,48 @@
1
1
  import Map from "ol/Map";
2
2
  import VectorLayer from "ol/layer/Vector";
3
3
  import VectorSource from "ol/source/Vector";
4
- import { MapJSONData, OptionsType, PointData } from '../types';
4
+ import { MapJSONData, PointOptions, ClusterOptions, PointData } from '../types';
5
5
  export default class Point {
6
6
  private map;
7
7
  constructor(map: Map);
8
+ /**
9
+ * 创建文本样式
10
+ * @private
11
+ * @param options 选项
12
+ * @param text 文本内容
13
+ * @returns 文本样式
14
+ */
15
+ private createTextStyle;
16
+ /**
17
+ * 创建图标样式
18
+ * @private
19
+ * @param options 选项
20
+ * @returns 图标样式
21
+ */
22
+ private createIconStyle;
23
+ /**
24
+ * 创建点样式
25
+ * @private
26
+ * @param options 选项
27
+ * @param item 数据项
28
+ * @returns 样式对象
29
+ */
30
+ private createPointStyle;
31
+ /**
32
+ * 创建集群样式
33
+ * @private
34
+ * @param options 选项
35
+ * @param name 名称
36
+ * @returns 样式对象
37
+ */
38
+ private createClusterStyle;
39
+ /**
40
+ * 配置图层属性
41
+ * @private
42
+ * @param layer 图层
43
+ * @param options 选项
44
+ */
45
+ private configureLayer;
8
46
  /**
9
47
  *
10
48
  * @param pointData
@@ -15,8 +53,8 @@ export default class Point {
15
53
  * hasImg: Boolean 是否显示图标
16
54
  * }
17
55
  */
18
- addPoint(pointData: PointData[], options: OptionsType): VectorLayer<VectorSource<import("ol/geom").Geometry>>;
19
- addClusterPoint(pointData: PointData[], options: OptionsType): void;
56
+ addPoint(pointData: PointData[], options: PointOptions): VectorLayer<VectorSource> | null;
57
+ addClusterPoint(pointData: PointData[], options: ClusterOptions): VectorLayer<VectorSource> | null;
20
58
  setTwinkleLayerFromPolygon(twinkleList: any[], className: string, key: string, json: MapJSONData): void;
21
59
  /**
22
60
  * 设置闪烁点
@@ -33,11 +71,19 @@ export default class Point {
33
71
  * @param zoom 缩放级别
34
72
  * @param duration 动画时长
35
73
  */
36
- locationAction(lgtd: number, lttd: number, zoom?: number, duration?: number): false | undefined;
74
+ locationAction(lgtd: number, lttd: number, zoom?: number, duration?: number): boolean;
37
75
  /**
38
76
  * 设置dom元素为点位
39
77
  */
40
- setDomPoint(id: string, lgtd: number, lttd: number): void;
78
+ setDomPoint(id: string, lgtd: number, lttd: number): boolean;
79
+ /**
80
+ * 设置vue组件为点位
81
+ * @param pointInfoList 点位信息列表
82
+ * @param template vue组件模板
83
+ * @param Vue Vue实例
84
+ * @returns 返回控制对象,包含显示、隐藏、移除方法
85
+ * @throws 当参数无效时抛出错误
86
+ */
41
87
  setDomPointVue(pointInfoList: any[], template: any, Vue: any): {
42
88
  setVisible: (visible: boolean) => void;
43
89
  remove: () => void;
@@ -3,18 +3,99 @@ import Overlay from 'ol/Overlay';
3
3
  import Feature from "ol/Feature";
4
4
  import { Point as olPoint } from "ol/geom";
5
5
  import { Text, Style, Fill, Stroke, Icon } from "ol/style";
6
- // import {Style, Icon, Text} from "ol/style";
7
6
  import VectorLayer from "ol/layer/Vector";
8
7
  import VectorSource from "ol/source/Vector";
9
8
  import { Cluster } from 'ol/source';
10
- import * as turf from 'turf';
9
+ import * as turf from '@turf/turf';
11
10
  import GeoJSON from "ol/format/GeoJSON";
12
- import DomPoint from "./DomPoint";
11
+ import DomPoint from './DomPoint';
13
12
  import MapTools from "./MapTools";
13
+ import { ValidationUtils } from '../utils/ValidationUtils';
14
14
  export default class Point {
15
15
  constructor(map) {
16
16
  this.map = map;
17
17
  }
18
+ /**
19
+ * 创建文本样式
20
+ * @private
21
+ * @param options 选项
22
+ * @param text 文本内容
23
+ * @returns 文本样式
24
+ */
25
+ createTextStyle(options, text) {
26
+ return new Text({
27
+ text: text,
28
+ font: options.textFont || '12px Calibri,sans-serif',
29
+ fill: new Fill({
30
+ color: options.textFillColor || '#FFF'
31
+ }),
32
+ stroke: new Stroke({
33
+ color: options.textStrokeColor || '#000',
34
+ width: options.textStrokeWidth || 3
35
+ }),
36
+ offsetY: options.textOffsetY || 20,
37
+ });
38
+ }
39
+ /**
40
+ * 创建图标样式
41
+ * @private
42
+ * @param options 选项
43
+ * @returns 图标样式
44
+ */
45
+ createIconStyle(options) {
46
+ const iconOptions = {
47
+ src: options.img,
48
+ scale: options.scale ?? 1,
49
+ };
50
+ if (options.iconColor) {
51
+ iconOptions.color = options.iconColor;
52
+ }
53
+ return new Icon(iconOptions);
54
+ }
55
+ /**
56
+ * 创建点样式
57
+ * @private
58
+ * @param options 选项
59
+ * @param item 数据项
60
+ * @returns 样式对象
61
+ */
62
+ createPointStyle(options, item) {
63
+ const style = {};
64
+ if (options.nameKey && item) {
65
+ style.text = this.createTextStyle(options, item[options.nameKey]);
66
+ }
67
+ if (options.hasImg || options.hasImg === undefined) {
68
+ style.image = this.createIconStyle(options);
69
+ }
70
+ return new Style(style);
71
+ }
72
+ /**
73
+ * 创建集群样式
74
+ * @private
75
+ * @param options 选项
76
+ * @param name 名称
77
+ * @returns 样式对象
78
+ */
79
+ createClusterStyle(options, name) {
80
+ const style = {};
81
+ if (options.nameKey) {
82
+ style.text = this.createTextStyle(options, name);
83
+ }
84
+ if (options.hasImg || options.hasImg === undefined) {
85
+ style.image = this.createIconStyle(options);
86
+ }
87
+ return new Style(style);
88
+ }
89
+ /**
90
+ * 配置图层属性
91
+ * @private
92
+ * @param layer 图层
93
+ * @param options 选项
94
+ */
95
+ configureLayer(layer, options) {
96
+ layer.setVisible(options.visible === undefined ? true : options.visible);
97
+ this.map.addLayer(layer);
98
+ }
18
99
  /**
19
100
  *
20
101
  * @param pointData
@@ -26,41 +107,20 @@ export default class Point {
26
107
  * }
27
108
  */
28
109
  addPoint(pointData, options) {
110
+ if (!ValidationUtils.validatePointData(pointData)) {
111
+ return null;
112
+ }
29
113
  const pointFeatureList = [];
30
114
  pointData.forEach((item) => {
115
+ if (!ValidationUtils.validateCoordinates(item)) {
116
+ return;
117
+ }
31
118
  const pointFeature = new Feature({
32
- // clickLocation: options.clickLocation,
33
- // all: JSON.stringify(item),
34
- rawData: item, //保存原始数据
119
+ rawData: item,
35
120
  type: options.layerName,
36
121
  geometry: new olPoint([item.lgtd, item.lttd])
37
122
  });
38
- const style = {};
39
- if (options.nameKey) {
40
- style.text = new Text({
41
- text: item[options.nameKey],
42
- font: options.textFont || '12px Calibri,sans-serif',
43
- fill: new Fill({
44
- color: options.textFillColor || '#FFF'
45
- }),
46
- stroke: new Stroke({
47
- color: options.textStrokeColor || '#000',
48
- width: options.textStrokeWidth || 3
49
- }),
50
- offsetY: options.textOffsetY || 20,
51
- });
52
- }
53
- if (options.hasImg || options.hasImg === undefined) {
54
- const iconOptions = {
55
- src: options.img,
56
- scale: options.scale ?? 1,
57
- };
58
- if (options.iconColor) {
59
- iconOptions.color = options.iconColor;
60
- }
61
- style.image = new Icon(iconOptions);
62
- }
63
- pointFeature.setStyle(new Style(style));
123
+ pointFeature.setStyle(this.createPointStyle(options, item));
64
124
  pointFeatureList.push(pointFeature);
65
125
  });
66
126
  const PointVectorLayer = new VectorLayer({
@@ -70,13 +130,18 @@ export default class Point {
70
130
  }),
71
131
  zIndex: options.zIndex || 21,
72
132
  });
73
- PointVectorLayer.setVisible(options.visible === undefined ? true : options.visible);
74
- this.map.addLayer(PointVectorLayer);
133
+ this.configureLayer(PointVectorLayer, options);
75
134
  return PointVectorLayer;
76
135
  }
77
136
  addClusterPoint(pointData, options) {
137
+ if (!ValidationUtils.validatePointData(pointData)) {
138
+ return null;
139
+ }
78
140
  const pointFeatureList = [];
79
141
  pointData.forEach(item => {
142
+ if (!ValidationUtils.validateCoordinates(item)) {
143
+ return;
144
+ }
80
145
  const pointFeature = new Feature({
81
146
  geometry: new olPoint([item.lgtd, item.lttd]),
82
147
  name: options.nameKey ? item[options.nameKey] : '',
@@ -87,45 +152,21 @@ export default class Point {
87
152
  features: pointFeatureList,
88
153
  });
89
154
  const clusterSource = new Cluster({
90
- distance: 40, // The distance for clustering in pixels
155
+ distance: options.distance || 40, // The distance for clustering in pixels
156
+ minDistance: options.minDistance || 0,
91
157
  source: source,
92
158
  });
93
159
  const clusterLayer = new VectorLayer({
94
160
  layerName: options.layerName,
95
161
  source: clusterSource,
96
- style: function (feature) {
162
+ style: (feature) => {
97
163
  const name = feature.get('features')[0].get(options.nameKey);
98
- const style = {};
99
- if (options.nameKey) {
100
- style.text = new Text({
101
- text: name,
102
- font: options.textFont || '12px Calibri,sans-serif',
103
- fill: new Fill({
104
- color: options.textFillColor || '#FFF'
105
- }),
106
- stroke: new Stroke({
107
- color: options.textStrokeColor || '#000',
108
- width: options.textStrokeWidth || 3
109
- }),
110
- offsetY: options.textOffsetY || 20,
111
- });
112
- }
113
- if (options.hasImg || options.hasImg === undefined) {
114
- const iconOptions = {
115
- src: options.img,
116
- scale: options.scale ?? 1,
117
- };
118
- if (options.iconColor) {
119
- iconOptions.color = options.iconColor;
120
- }
121
- style.image = new Icon(iconOptions);
122
- }
123
- return new Style(style);
164
+ return this.createClusterStyle(options, name);
124
165
  },
125
166
  zIndex: options.zIndex || 21,
126
167
  });
127
- clusterLayer.setVisible(options.visible === undefined ? true : options.visible);
128
- this.map.addLayer(clusterLayer);
168
+ this.configureLayer(clusterLayer, options);
169
+ return clusterLayer;
129
170
  }
130
171
  // 在流域中心添加闪烁点位
131
172
  setTwinkleLayerFromPolygon(twinkleList, className, key, json) {
@@ -233,58 +274,101 @@ export default class Point {
233
274
  * @param duration 动画时长
234
275
  */
235
276
  locationAction(lgtd, lttd, zoom = 20, duration = 3000) {
236
- if (!(lgtd && lttd)) {
237
- console.error('[地图定位]', '经纬度不能为空');
277
+ if (!ValidationUtils.validateLngLat(lgtd, lttd)) {
278
+ return false;
279
+ }
280
+ try {
281
+ this.map.getView().animate({ center: [lgtd, lttd], zoom, duration });
282
+ return true;
283
+ }
284
+ catch (error) {
285
+ console.error('[地图定位]', '定位失败:', error);
238
286
  return false;
239
287
  }
240
- this.map.getView().animate({ center: [lgtd, lttd], zoom, duration });
241
288
  }
242
289
  /**
243
290
  * 设置dom元素为点位
244
291
  */
245
292
  setDomPoint(id, lgtd, lttd) {
293
+ if (!id) {
294
+ console.error('Element ID is required');
295
+ return false;
296
+ }
297
+ if (!ValidationUtils.validateLngLat(lgtd, lttd)) {
298
+ return false;
299
+ }
246
300
  const el = document.getElementById(id);
247
- if (el) {
301
+ if (!el) {
302
+ console.error(`Element with id '${id}' not found`);
303
+ return false;
304
+ }
305
+ try {
248
306
  const anchor = new Overlay({
249
307
  id: id,
250
308
  element: el,
251
309
  positioning: 'center-center',
252
310
  stopEvent: false
253
- // autoPan: true,
254
- // autoPanAnimation: {
255
- // duration: 250
256
- // },
257
311
  });
258
312
  anchor.setPosition([lgtd, lttd]);
259
313
  this.map.addOverlay(anchor);
314
+ return true;
315
+ }
316
+ catch (error) {
317
+ console.error('Failed to set DOM point:', error);
318
+ return false;
260
319
  }
261
320
  }
321
+ /**
322
+ * 设置vue组件为点位
323
+ * @param pointInfoList 点位信息列表
324
+ * @param template vue组件模板
325
+ * @param Vue Vue实例
326
+ * @returns 返回控制对象,包含显示、隐藏、移除方法
327
+ * @throws 当参数无效时抛出错误
328
+ */
262
329
  setDomPointVue(pointInfoList, template, Vue) {
263
- const layer = pointInfoList.map((pointInfo) => {
264
- return new DomPoint(this.map, {
265
- Vue,
266
- Template: template,
267
- lgtd: pointInfo.lgtd,
268
- lttd: pointInfo.lttd,
269
- props: {
270
- stationInfo: {
271
- type: Object,
272
- default: pointInfo
273
- }
274
- },
275
- });
276
- });
277
- return {
278
- setVisible: (visible) => {
279
- layer.forEach((item) => {
280
- item.setVisible(visible);
281
- });
282
- },
283
- remove: () => {
284
- layer.forEach((item) => {
285
- item.remove();
330
+ if (!pointInfoList || !Array.isArray(pointInfoList) || pointInfoList.length === 0) {
331
+ throw new Error('Valid point info list is required');
332
+ }
333
+ if (!template) {
334
+ throw new Error('Vue template is required');
335
+ }
336
+ if (!Vue) {
337
+ throw new Error('Vue instance is required');
338
+ }
339
+ try {
340
+ const layer = pointInfoList.map((pointInfo) => {
341
+ if (!ValidationUtils.validateLngLat(pointInfo.lgtd, pointInfo.lttd)) {
342
+ throw new Error('Valid longitude and latitude are required for each point');
343
+ }
344
+ return new DomPoint(this.map, {
345
+ Vue,
346
+ Template: template,
347
+ lgtd: pointInfo.lgtd,
348
+ lttd: pointInfo.lttd,
349
+ props: {
350
+ stationInfo: {
351
+ type: Object,
352
+ default: pointInfo
353
+ }
354
+ },
286
355
  });
287
- }
288
- };
356
+ });
357
+ return {
358
+ setVisible: (visible) => {
359
+ layer.forEach((item) => {
360
+ item.setVisible(visible);
361
+ });
362
+ },
363
+ remove: () => {
364
+ layer.forEach((item) => {
365
+ item.remove();
366
+ });
367
+ }
368
+ };
369
+ }
370
+ catch (error) {
371
+ throw new Error(`Failed to create DOM points: ${error}`);
372
+ }
289
373
  }
290
374
  }
@@ -1,39 +1,78 @@
1
1
  import Map from "ol/Map";
2
2
  import VectorLayer from "ol/layer/Vector";
3
3
  import VectorSource from "ol/source/Vector";
4
- import { Image as ImageLayer } from "ol/layer";
5
- import { Geometry } from "ol/geom";
6
- import { OptionsType, MapJSONData, PointData, HeatMapOptions } from '../types';
4
+ import { Image as ImageLayer, Heatmap } from "ol/layer";
5
+ import { PolygonOptions, MapJSONData, PointData, HeatMapOptions, ImageLayerData, MaskLayerOptions, FeatureColorUpdateOptions } from '../types';
6
+ /**
7
+ * Polygon 类用于处理地图上的面要素操作
8
+ * 包括添加多边形、边框、图片图层、热力图等功能
9
+ */
7
10
  export default class Polygon {
8
- map: Map;
11
+ private map;
9
12
  private colorMap;
10
13
  [key: string]: any;
14
+ /**
15
+ * 构造函数
16
+ * @param map OpenLayers 地图实例
17
+ */
11
18
  constructor(map: Map);
12
19
  /**
13
20
  * 获取等级颜色
14
- * @param lev
21
+ * @param lev 等级值,支持字符串或数字
22
+ * @returns 对应等级的颜色值,如果等级不存在则返回默认颜色
15
23
  */
16
24
  getLevColor(lev: string | number): string;
17
25
  /**
18
- * 添加 地图 边框 图层
19
- * @param data 图层数据
20
- * @param options 图层配置
26
+ * 添加地图边框图层
27
+ * @param data 图层数据,必须是有效的 GeoJSON 格式
28
+ * @param options 图层配置选项
29
+ * @returns 创建的图层实例
30
+ * @throws 当数据格式无效时抛出错误
31
+ */
32
+ addBorderPolygon(data: MapJSONData, options?: PolygonOptions): VectorLayer<VectorSource>;
33
+ /**
34
+ * 添加多边形图层
35
+ * @param dataJSON GeoJSON 数据
36
+ * @param options 图层配置选项
37
+ * @returns 创建的矢量图层
38
+ * @throws 当数据格式无效时抛出错误
39
+ */
40
+ addPolygon(dataJSON: MapJSONData, options?: PolygonOptions): VectorLayer<VectorSource>;
41
+ /**
42
+ * 设置要素样式
43
+ * @param features 要素数组
44
+ * @param options 样式配置选项
45
+ */
46
+ private setFeatureStyles;
47
+ /**
48
+ * 获取要素文本
49
+ * @param feature 要素对象
50
+ * @param options 配置选项
51
+ * @returns 文本内容
52
+ */
53
+ private getFeatureText;
54
+ /**
55
+ * 适应图层视图
56
+ * @param layer 图层对象
21
57
  */
22
- addBorderPolygon(data: MapJSONData, options?: OptionsType): void;
23
- addPolygon(dataJSON: MapJSONData, options?: OptionsType): VectorLayer<VectorSource<Geometry>>;
58
+ private fitViewToLayer;
24
59
  /**
25
60
  * 根据数据数组更新某个面颜色
26
61
  * @param layerName 图层名称
27
- * @param colorObj 数据 不传或者传{}则重置所有颜色
28
- * colorObj:{
29
- * 对应geojson文件中的索引字段[propName]: 'rgba(255, 0, 0, 0.6)', // 颜色
30
- * ...
31
- * }
62
+ * @param colorObj 颜色映射对象,键为要素属性值,值为颜色字符串
32
63
  * @param options 配置项
64
+ * @throws 当图层不存在时抛出错误
33
65
  */
34
66
  updateFeatureColor(layerName: string, colorObj?: {
35
67
  [propName: string]: string;
36
- }, options?: OptionsType): void;
68
+ }, options?: FeatureColorUpdateOptions): void;
69
+ /**
70
+ * 更新单个要素的颜色
71
+ * @param feature 要素对象
72
+ * @param colorObj 颜色映射对象
73
+ * @param options 配置选项
74
+ */
75
+ private updateSingleFeatureColor;
37
76
  /**
38
77
  * 设置外围蒙版图层
39
78
  *
@@ -51,12 +90,25 @@ export default class Polygon {
51
90
  }): void;
52
91
  /**
53
92
  * 添加图片图层
54
- * @param layerName 图层名称
55
- * @param img 图片地址
56
- * @param extent 图片范围(对角线坐标) [minx, miny, maxx, maxy]
57
- * @param options 图层配置
93
+ * @param imageData 图片数据,包含url和extent
94
+ * @param options 配置项
95
+ * @returns 创建的图片图层
96
+ * @throws 当数据格式无效时抛出错误
97
+ */
98
+ addImageLayer(imageData: ImageLayerData, options?: PolygonOptions): ImageLayer<any>;
99
+ /**
100
+ * 添加热力图图层
101
+ * @param pointData 点数据数组
102
+ * @param options 热力图配置
103
+ */
104
+ addHeatmap(pointData: PointData[], options?: HeatMapOptions): Heatmap;
105
+ /**
106
+ * 添加遮罩图层
107
+ * @param data GeoJSON格式的遮罩数据
108
+ * @param options 配置项
109
+ * @returns 创建的遮罩图层
110
+ * @throws 当数据格式无效时抛出错误
58
111
  */
59
- addImage(layerName: string, img?: string, extent?: number[], options?: OptionsType): import("ol/layer/Base").default | VectorLayer<VectorSource<Geometry>> | ImageLayer<import("ol/source").Image>;
60
- addHeatmap(layerName: string, pointData: PointData[], options: HeatMapOptions): void;
112
+ addMaskLayer(data: any, options?: MaskLayerOptions): VectorLayer<VectorSource>;
61
113
  removePolygonLayer(layerName: string): void;
62
114
  }