my-openlayer 0.1.17 → 1.0.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.
@@ -0,0 +1,257 @@
1
+ import { ErrorHandler, ErrorType } from '../utils/ErrorHandler';
2
+ /**
3
+ * 事件管理器类
4
+ * 用于统一管理地图事件的注册、触发和移除
5
+ */
6
+ export class EventManager {
7
+ /**
8
+ * 构造函数
9
+ * @param map OpenLayers地图实例
10
+ */
11
+ constructor(map) {
12
+ this.listeners = new Map();
13
+ this.eventCounters = new Map();
14
+ ErrorHandler.validateMap(map);
15
+ this.map = map;
16
+ this.initializeEventCounters();
17
+ }
18
+ /**
19
+ * 初始化事件计数器
20
+ */
21
+ initializeEventCounters() {
22
+ const eventTypes = ['click', 'dblclick', 'hover', 'moveend', 'zoomend', 'pointermove'];
23
+ eventTypes.forEach(type => {
24
+ this.eventCounters.set(type, 0);
25
+ });
26
+ }
27
+ /**
28
+ * 注册事件监听器
29
+ * @param type 事件类型
30
+ * @param callback 回调函数
31
+ * @param options 选项
32
+ * @returns 事件监听器ID
33
+ */
34
+ on(type, callback, options) {
35
+ ErrorHandler.validate(typeof callback === 'function', 'Event callback must be a function', { type, callback });
36
+ const id = this.generateListenerId(type);
37
+ const listener = {
38
+ id,
39
+ type,
40
+ callback,
41
+ options
42
+ };
43
+ this.listeners.set(id, listener);
44
+ this.attachMapEvent(type);
45
+ return id;
46
+ }
47
+ /**
48
+ * 移除事件监听器
49
+ * @param id 监听器ID
50
+ */
51
+ off(id) {
52
+ const listener = this.listeners.get(id);
53
+ if (!listener) {
54
+ return false;
55
+ }
56
+ this.listeners.delete(id);
57
+ this.detachMapEventIfNeeded(listener.type);
58
+ return true;
59
+ }
60
+ /**
61
+ * 移除指定类型的所有事件监听器
62
+ * @param type 事件类型
63
+ */
64
+ offAll(type) {
65
+ const idsToRemove = [];
66
+ this.listeners.forEach((listener, id) => {
67
+ if (listener.type === type) {
68
+ idsToRemove.push(id);
69
+ }
70
+ });
71
+ idsToRemove.forEach(id => {
72
+ this.listeners.delete(id);
73
+ });
74
+ this.detachMapEventIfNeeded(type);
75
+ }
76
+ /**
77
+ * 清除所有事件监听器
78
+ */
79
+ clear() {
80
+ this.listeners.clear();
81
+ this.eventCounters.forEach((_, type) => {
82
+ this.detachMapEventIfNeeded(type);
83
+ });
84
+ }
85
+ /**
86
+ * 获取指定类型的监听器数量
87
+ * @param type 事件类型
88
+ */
89
+ getListenerCount(type) {
90
+ let count = 0;
91
+ this.listeners.forEach((listener) => {
92
+ if (listener.type === type) {
93
+ count++;
94
+ }
95
+ });
96
+ return count;
97
+ }
98
+ /**
99
+ * 生成监听器ID
100
+ * @param type 事件类型
101
+ */
102
+ generateListenerId(type) {
103
+ const counter = this.eventCounters.get(type) || 0;
104
+ this.eventCounters.set(type, counter + 1);
105
+ return `${type}_${counter + 1}_${Date.now()}`;
106
+ }
107
+ /**
108
+ * 附加地图事件
109
+ * @param type 事件类型
110
+ */
111
+ attachMapEvent(type) {
112
+ const existingListeners = this.getListenerCount(type);
113
+ if (existingListeners > 1) {
114
+ return; // 已经附加过该类型的事件
115
+ }
116
+ switch (type) {
117
+ case 'click':
118
+ this.map.on('click', this.handleClickEvent.bind(this));
119
+ break;
120
+ case 'dblclick':
121
+ this.map.on('dblclick', this.handleDblClickEvent.bind(this));
122
+ break;
123
+ case 'hover':
124
+ case 'pointermove':
125
+ this.map.on('pointermove', this.handlePointerMoveEvent.bind(this));
126
+ break;
127
+ case 'moveend':
128
+ this.map.on('moveend', this.handleMoveEndEvent.bind(this));
129
+ break;
130
+ case 'zoomend':
131
+ this.map.getView().on('change:resolution', this.handleZoomEndEvent.bind(this));
132
+ break;
133
+ }
134
+ }
135
+ /**
136
+ * 分离地图事件(如果不再需要)
137
+ * @param type 事件类型
138
+ */
139
+ detachMapEventIfNeeded(type) {
140
+ const remainingListeners = this.getListenerCount(type);
141
+ if (remainingListeners > 0) {
142
+ return; // 还有其他监听器需要该事件
143
+ }
144
+ // 注意:OpenLayers 不提供直接移除特定事件监听器的方法
145
+ // 这里只是示例,实际实现可能需要保存事件监听器的引用
146
+ console.warn(`Event type '${type}' detachment not fully implemented`);
147
+ }
148
+ /**
149
+ * 处理点击事件
150
+ * @param event 地图浏览器事件
151
+ */
152
+ handleClickEvent(event) {
153
+ const eventData = this.createEventData('click', event);
154
+ this.triggerListeners('click', eventData);
155
+ }
156
+ /**
157
+ * 处理双击事件
158
+ * @param event 地图浏览器事件
159
+ */
160
+ handleDblClickEvent(event) {
161
+ const eventData = this.createEventData('dblclick', event);
162
+ this.triggerListeners('dblclick', eventData);
163
+ }
164
+ /**
165
+ * 处理指针移动事件
166
+ * @param event 地图浏览器事件
167
+ */
168
+ handlePointerMoveEvent(event) {
169
+ const eventData = this.createEventData('pointermove', event);
170
+ this.triggerListeners('hover', eventData);
171
+ this.triggerListeners('pointermove', eventData);
172
+ }
173
+ /**
174
+ * 处理移动结束事件
175
+ */
176
+ handleMoveEndEvent() {
177
+ const eventData = {
178
+ type: 'moveend',
179
+ zoom: this.map.getView().getZoom(),
180
+ coordinate: this.map.getView().getCenter()
181
+ };
182
+ this.triggerListeners('moveend', eventData);
183
+ }
184
+ /**
185
+ * 处理缩放结束事件
186
+ */
187
+ handleZoomEndEvent() {
188
+ const eventData = {
189
+ type: 'zoomend',
190
+ zoom: this.map.getView().getZoom(),
191
+ coordinate: this.map.getView().getCenter()
192
+ };
193
+ this.triggerListeners('zoomend', eventData);
194
+ }
195
+ /**
196
+ * 创建事件数据
197
+ * @param type 事件类型
198
+ * @param event 原始事件
199
+ */
200
+ createEventData(type, event) {
201
+ const pixel = this.map.getEventPixel(event.originalEvent);
202
+ const features = this.map.getFeaturesAtPixel(pixel);
203
+ return {
204
+ type,
205
+ originalEvent: event.originalEvent,
206
+ coordinate: event.coordinate,
207
+ pixel,
208
+ features,
209
+ feature: features.length > 0 ? features[0] : undefined
210
+ };
211
+ }
212
+ /**
213
+ * 触发监听器
214
+ * @param type 事件类型
215
+ * @param eventData 事件数据
216
+ */
217
+ triggerListeners(type, eventData) {
218
+ const typeListeners = [];
219
+ this.listeners.forEach((listener) => {
220
+ if (listener.type === type) {
221
+ typeListeners.push(listener);
222
+ }
223
+ });
224
+ typeListeners.forEach((listener) => {
225
+ try {
226
+ // 应用过滤器
227
+ if (listener.options?.filter && !listener.options.filter(eventData)) {
228
+ return;
229
+ }
230
+ // 执行回调
231
+ listener.callback(eventData);
232
+ // 如果是一次性监听器,移除它
233
+ if (listener.options?.once) {
234
+ this.off(listener.id);
235
+ }
236
+ }
237
+ catch (error) {
238
+ ErrorHandler.getInstance().createAndHandleError(`Error in event listener: ${error}`, ErrorType.COMPONENT_ERROR, { listener, eventData, error });
239
+ }
240
+ });
241
+ }
242
+ /**
243
+ * 获取监听器信息(用于调试)
244
+ */
245
+ getListenersInfo() {
246
+ const result = [];
247
+ this.listeners.forEach((listener) => {
248
+ result.push({
249
+ id: listener.id,
250
+ type: listener.type,
251
+ hasFilter: !!listener.options?.filter,
252
+ isOnce: !!listener.options?.once
253
+ });
254
+ });
255
+ return result;
256
+ }
257
+ }
@@ -2,15 +2,31 @@ import Map from "ol/Map";
2
2
  import VectorSource from "ol/source/Vector";
3
3
  import VectorLayer from "ol/layer/Vector";
4
4
  import { Style } from "ol/style";
5
- import { OptionsType, MapJSONData } from "../types";
5
+ import { LineOptions, MapJSONData } from "../types";
6
+ /**
7
+ * 线要素管理类
8
+ * 用于在地图上添加和管理线要素
9
+ */
6
10
  export default class Line {
7
- private map;
11
+ private readonly map;
8
12
  riverLayerList: any[];
9
13
  riverLayerShow: boolean;
10
14
  [propertyName: string]: any;
15
+ /**
16
+ * 构造函数
17
+ * @param map OpenLayers地图实例
18
+ * @throws 当地图实例无效时抛出错误
19
+ */
11
20
  constructor(map: Map);
12
- addLine(data: MapJSONData, options: OptionsType): VectorLayer<VectorSource<import("ol/geom").Geometry>>;
13
- addRiverLayersByZoom(fyRiverJson: MapJSONData, options?: OptionsType): void;
21
+ /**
22
+ * 添加线要素
23
+ * @param data GeoJSON格式的线数据
24
+ * @param options 配置项
25
+ * @returns 创建的矢量图层
26
+ * @throws 当数据格式无效时抛出错误
27
+ */
28
+ addLine(data: MapJSONData, options: LineOptions): VectorLayer<VectorSource>;
29
+ addRiverLayersByZoom(fyRiverJson: MapJSONData, options?: LineOptions): void;
14
30
  showRiverLayer(show: boolean): void;
15
31
  showRiverLayerByZoom(): void;
16
32
  addRiverWidthByLev(arr?: any): void;
package/dist/core/Line.js CHANGED
@@ -3,18 +3,53 @@ import GeoJSON from "ol/format/GeoJSON";
3
3
  import VectorLayer from "ol/layer/Vector";
4
4
  import { Stroke, Style } from "ol/style";
5
5
  import MapTools from "./MapTools";
6
+ /**
7
+ * 线要素管理类
8
+ * 用于在地图上添加和管理线要素
9
+ */
6
10
  export default class Line {
11
+ /**
12
+ * 构造函数
13
+ * @param map OpenLayers地图实例
14
+ * @throws 当地图实例无效时抛出错误
15
+ */
7
16
  constructor(map) {
8
17
  this.riverLayerList = [];
9
18
  this.riverLayerShow = false;
19
+ if (!map) {
20
+ throw new Error('Map instance is required');
21
+ }
10
22
  this.map = map;
11
23
  }
24
+ /**
25
+ * 添加线要素
26
+ * @param data GeoJSON格式的线数据
27
+ * @param options 配置项
28
+ * @returns 创建的矢量图层
29
+ * @throws 当数据格式无效时抛出错误
30
+ */
12
31
  addLine(data, options) {
32
+ if (!data) {
33
+ throw new Error('Line data is required');
34
+ }
35
+ if (!options || !options.type) {
36
+ throw new Error('Options with type is required');
37
+ }
38
+ let features;
39
+ try {
40
+ features = new GeoJSON().readFeatures(data);
41
+ }
42
+ catch (error) {
43
+ throw new Error(`Invalid GeoJSON data: ${error}`);
44
+ }
45
+ if (!features || features.length === 0) {
46
+ console.warn('No features found in line data');
47
+ }
13
48
  const layer = new VectorLayer({
14
49
  name: options.layerName,
15
50
  layerName: options.layerName,
16
51
  source: new VectorSource({
17
- features: (new GeoJSON()).readFeatures(data)
52
+ features: features
18
53
  }),
19
54
  style: function (feature) {
20
55
  feature.set('type', options.type);
@@ -1,5 +1,7 @@
1
1
  /**
2
- * 地图底图图层
2
+ * 地图底图图层管理类
3
+ * 提供天地图底图、注记图层、GeoServer图层等功能
4
+ * 支持图层切换、裁剪等高级功能
3
5
  */
4
6
  import Map from "ol/Map";
5
7
  import { Tile as TileLayer } from "ol/layer";
@@ -7,30 +9,196 @@ import { TileWMS } from "ol/source";
7
9
  import WMTSTileGrid from "ol/tilegrid/WMTS";
8
10
  import XYZ from "ol/source/XYZ";
9
11
  import { MapLayersOptions, TiandituType, AnnotationLayerOptions } from "../types";
12
+ /**
13
+ * GeoServer图层选项接口
14
+ */
15
+ interface GeoServerLayerOptions {
16
+ /** 图层层级 */
17
+ zIndex?: number;
18
+ /** 图层可见性 */
19
+ visible?: boolean;
20
+ /** WMS版本 */
21
+ version?: '1.1.1' | '1.3.0';
22
+ /** 服务器类型 */
23
+ serverType?: string;
24
+ /** 跨域设置 */
25
+ crossOrigin?: string;
26
+ /** WMS参数 */
27
+ params?: Record<string, any>;
28
+ }
29
+ /**
30
+ * 天地图图层选项接口
31
+ */
32
+ interface TiandituLayerOptions {
33
+ /** 图层类型 */
34
+ type: TiandituType;
35
+ /** 天地图token */
36
+ token: string;
37
+ /** 图层层级 */
38
+ zIndex: number;
39
+ /** 图层可见性 */
40
+ visible: boolean;
41
+ }
42
+ /**
43
+ * 地图底图图层管理类
44
+ */
10
45
  export default class MapBaseLayers {
11
- private map;
46
+ private readonly map;
12
47
  private readonly options;
13
- private readonly layers;
48
+ private layers;
49
+ private readonly errorHandler;
50
+ private currentBaseLayerType;
51
+ /**
52
+ * 构造函数
53
+ * @param map OpenLayers地图实例
54
+ * @param options 图层配置选项
55
+ */
14
56
  constructor(map: Map, options: MapLayersOptions);
57
+ /**
58
+ * 验证构造函数参数
59
+ * @param map 地图实例
60
+ * @param options 配置选项
61
+ * @private
62
+ */
63
+ private validateConstructorParams;
64
+ /**
65
+ * 合并默认配置选项
66
+ * @param options 用户配置选项
67
+ * @returns 合并后的配置选项
68
+ * @private
69
+ */
70
+ private mergeDefaultOptions;
71
+ /**
72
+ * 初始化图层
73
+ * @private
74
+ */
75
+ private initializeLayers;
76
+ /**
77
+ * 初始化天地图图层
78
+ * @private
79
+ */
80
+ private initTiandituLayers;
81
+ /**
82
+ * 添加注记图层
83
+ * @param token 天地图token
84
+ * @param baseZIndex 基础层级
85
+ * @private
86
+ */
87
+ private addAnnotationLayers;
88
+ /**
89
+ * 切换底图图层
90
+ * @param type 图层类型
91
+ */
15
92
  switchBaseLayer(type: TiandituType): void;
16
- initLayer(): void;
17
- addAnnotationLayer(options: Omit<AnnotationLayerOptions, 'token'>): void;
93
+ /**
94
+ * 获取当前底图类型
95
+ * @returns 当前底图类型
96
+ */
97
+ getCurrentBaseLayerType(): string | null;
98
+ /**
99
+ * 获取可用的图层类型列表
100
+ * @returns 图层类型数组
101
+ */
102
+ getAvailableLayerTypes(): string[];
103
+ /**
104
+ * 检查指定图层类型是否存在
105
+ * @param type 图层类型
106
+ * @returns 是否存在
107
+ */
108
+ hasLayerType(type: string): boolean;
109
+ /**
110
+ * 添加注记图层(实例方法)
111
+ * @param options 注记图层选项(不包含token)
112
+ * @returns 创建的图层
113
+ */
114
+ addAnnotationLayer(options: Omit<AnnotationLayerOptions, 'token'>): TileLayer<XYZ>;
115
+ /**
116
+ * 添加注记图层(静态方法)
117
+ * @param map 地图实例
118
+ * @param options 注记图层选项
119
+ * @returns 创建的图层
120
+ */
18
121
  static addAnnotationLayer(map: Map, options: AnnotationLayerOptions): TileLayer<XYZ>;
19
- addMapLayer(): void;
20
- createLayer(layer: any): any;
21
- addGeoServerLayer(url: string, layer: string, options: {
22
- zIndex?: number;
23
- visible?: boolean;
24
- }): TileLayer<TileWMS>;
25
- static getTiandiTuLayer(options: {
26
- type: TiandituType;
27
- token: string;
28
- zIndex: number;
29
- visible: boolean;
30
- }): TileLayer<XYZ>;
31
- /**
32
- * 地图注记
122
+ /**
123
+ * 将所有图层添加到地图
124
+ * @private
125
+ */
126
+ private addMapLayer;
127
+ /**
128
+ * 处理图层(应用裁剪等)
129
+ * @param layer 原始图层
130
+ * @returns 处理后的图层
131
+ * @private
132
+ */
133
+ private processLayer;
134
+ /**
135
+ * 添加GeoServer图层
136
+ * @param url GeoServer服务URL
137
+ * @param layerName 图层名称
138
+ * @param options 图层选项
139
+ * @returns 创建的WMS图层
140
+ */
141
+ addGeoServerLayer(url: string, layerName: string, options?: GeoServerLayerOptions): TileLayer<TileWMS>;
142
+ /**
143
+ * 创建天地图图层(实例方法)
144
+ * @param options 天地图图层选项
145
+ * @returns 创建的图层
146
+ * @private
147
+ */
148
+ private createTiandituLayer;
149
+ /**
150
+ * 创建注记图层(实例方法)
151
+ * @param options 注记图层选项
152
+ * @returns 创建的图层
153
+ * @private
154
+ */
155
+ private createAnnotationLayer;
156
+ /**
157
+ * 创建天地图底图图层(静态方法)
158
+ * @param options 天地图图层选项
159
+ * @returns 创建的图层
160
+ */
161
+ static getTiandiTuLayer(options: TiandituLayerOptions): TileLayer<XYZ>;
162
+ /**
163
+ * 创建天地图注记图层(静态方法)
164
+ * @param options 注记图层选项
165
+ * @returns 创建的图层
166
+ */
167
+ static createAnnotationLayer(options: AnnotationLayerOptions): TileLayer<XYZ>;
168
+ /**
169
+ * 获取天地图注记图层(向后兼容的静态方法)
170
+ * @param options 注记图层选项
171
+ * @returns 创建的图层
172
+ * @deprecated 使用 createAnnotationLayer 替代
33
173
  */
34
174
  static getAnnotationLayer(options: AnnotationLayerOptions): TileLayer<XYZ>;
175
+ /**
176
+ * 创建WMTS瓦片网格
177
+ * @param length 层级数量
178
+ * @returns WMTS瓦片网格
179
+ */
35
180
  static getTileGrid(length: number): WMTSTileGrid;
181
+ /**
182
+ * 移除指定类型的图层
183
+ * @param type 图层类型
184
+ */
185
+ removeLayersByType(type: string): void;
186
+ /**
187
+ * 清除所有图层
188
+ */
189
+ clearAllLayers(): void;
190
+ /**
191
+ * 获取图层数量统计
192
+ * @returns 图层统计信息
193
+ */
194
+ getLayerStats(): {
195
+ totalTypes: number;
196
+ totalLayers: number;
197
+ layersByType: Record<string, number>;
198
+ };
199
+ /**
200
+ * 销毁实例,清理资源
201
+ */
202
+ destroy(): void;
36
203
  }
204
+ export {};