my-openlayer 2.0.0 → 2.1.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.
@@ -1,316 +1,316 @@
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
- this.mapEventListeners = new Map();
15
- ErrorHandler.validateMap(map);
16
- this.map = map;
17
- this.initializeEventCounters();
18
- }
19
- /**
20
- * 初始化事件计数器
21
- */
22
- initializeEventCounters() {
23
- const eventTypes = ['click', 'dblclick', 'hover', 'moveend', 'zoomend', 'pointermove', 'rendercomplete', 'error'];
24
- eventTypes.forEach(type => {
25
- this.eventCounters.set(type, 0);
26
- });
27
- }
28
- /**
29
- * 注册事件监听器
30
- * @param type 事件类型
31
- * @param callback 回调函数
32
- * @param options 选项
33
- * @returns 事件监听器ID
34
- */
35
- on(type, callback, options) {
36
- ErrorHandler.validate(typeof callback === 'function', 'Event callback must be a function', { type, callback });
37
- const id = this.generateListenerId(type);
38
- const listener = {
39
- id,
40
- type,
41
- callback,
42
- options
43
- };
44
- this.listeners.set(id, listener);
45
- this.attachMapEvent(type);
46
- return id;
47
- }
48
- /**
49
- * 移除事件监听器
50
- * @param id 监听器ID
51
- */
52
- off(id) {
53
- const listener = this.listeners.get(id);
54
- if (!listener) {
55
- return false;
56
- }
57
- this.listeners.delete(id);
58
- // 如果该类型没有其他监听器了,移除地图事件监听器
59
- const remainingListeners = this.getListenerCount(listener.type);
60
- if (remainingListeners === 0) {
61
- this.detachMapEvent(listener.type);
62
- }
63
- return true;
64
- }
65
- /**
66
- * 移除指定类型的所有事件监听器
67
- * @param type 事件类型
68
- */
69
- offAll(type) {
70
- const idsToRemove = [];
71
- this.listeners.forEach((listener, id) => {
72
- if (listener.type === type) {
73
- idsToRemove.push(id);
74
- }
75
- });
76
- idsToRemove.forEach(id => {
77
- this.listeners.delete(id);
78
- });
79
- // 移除对应的地图事件监听器
80
- if (idsToRemove.length > 0) {
81
- this.detachMapEvent(type);
82
- }
83
- }
84
- /**
85
- * 清除所有事件监听器
86
- */
87
- clear() {
88
- this.listeners.clear();
89
- // 移除所有地图事件监听器
90
- this.mapEventListeners.forEach((_, type) => {
91
- this.detachMapEvent(type);
92
- });
93
- }
94
- /**
95
- * 获取指定类型的监听器数量
96
- * @param type 事件类型
97
- */
98
- getListenerCount(type) {
99
- let count = 0;
100
- this.listeners.forEach((listener) => {
101
- if (listener.type === type) {
102
- count++;
103
- }
104
- });
105
- return count;
106
- }
107
- /**
108
- * 生成监听器ID
109
- * @param type 事件类型
110
- */
111
- generateListenerId(type) {
112
- const counter = this.eventCounters.get(type) || 0;
113
- this.eventCounters.set(type, counter + 1);
114
- return `${type}_${counter + 1}_${Date.now()}`;
115
- }
116
- /**
117
- * 附加地图事件
118
- * @param type 事件类型
119
- */
120
- attachMapEvent(type) {
121
- const existingListeners = this.getListenerCount(type);
122
- if (existingListeners > 1) {
123
- return; // 已经附加过该类型的事件
124
- }
125
- // 如果已经有地图事件监听器,先移除
126
- if (this.mapEventListeners.has(type)) {
127
- this.detachMapEvent(type);
128
- }
129
- let eventHandler;
130
- let target = this.map;
131
- let eventName;
132
- switch (type) {
133
- case 'click':
134
- eventHandler = this.handleClickEvent.bind(this);
135
- eventName = 'click';
136
- break;
137
- case 'dblclick':
138
- eventHandler = this.handleDblClickEvent.bind(this);
139
- eventName = 'dblclick';
140
- break;
141
- case 'hover':
142
- case 'pointermove':
143
- eventHandler = this.handlePointerMoveEvent.bind(this);
144
- eventName = 'pointermove';
145
- break;
146
- case 'moveend':
147
- eventHandler = this.handleMoveEndEvent.bind(this);
148
- eventName = 'moveend';
149
- break;
150
- case 'zoomend':
151
- eventHandler = this.handleZoomEndEvent.bind(this);
152
- target = this.map.getView();
153
- eventName = 'change:resolution';
154
- break;
155
- case 'rendercomplete':
156
- eventHandler = this.handleRenderCompleteEvent.bind(this);
157
- eventName = 'rendercomplete';
158
- this.map.once(eventName, eventHandler);
159
- this.mapEventListeners.set(type, { handler: eventHandler, target, eventName, isOnce: true });
160
- return;
161
- case 'error':
162
- eventHandler = this.handleErrorEvent.bind(this);
163
- eventName = 'error';
164
- break;
165
- default:
166
- return;
167
- }
168
- target.on(eventName, eventHandler);
169
- this.mapEventListeners.set(type, { handler: eventHandler, target, eventName, isOnce: false });
170
- }
171
- /**
172
- * 移除地图事件监听器
173
- * @param type 事件类型
174
- */
175
- detachMapEvent(type) {
176
- const mapListener = this.mapEventListeners.get(type);
177
- if (!mapListener) {
178
- return;
179
- }
180
- const { handler, target, eventName } = mapListener;
181
- target.un(eventName, handler);
182
- this.mapEventListeners.delete(type);
183
- }
184
- /**
185
- * 处理点击事件
186
- * @param event 地图浏览器事件
187
- */
188
- handleClickEvent(event) {
189
- const eventData = this.createEventData('click', event);
190
- this.triggerListeners('click', eventData);
191
- }
192
- /**
193
- * 处理双击事件
194
- * @param event 地图浏览器事件
195
- */
196
- handleDblClickEvent(event) {
197
- const eventData = this.createEventData('dblclick', event);
198
- this.triggerListeners('dblclick', eventData);
199
- }
200
- /**
201
- * 处理指针移动事件
202
- * @param event 地图浏览器事件
203
- */
204
- handlePointerMoveEvent(event) {
205
- const eventData = this.createEventData('pointermove', event);
206
- this.triggerListeners('hover', eventData);
207
- this.triggerListeners('pointermove', eventData);
208
- }
209
- /**
210
- * 处理移动结束事件
211
- */
212
- handleMoveEndEvent() {
213
- const eventData = {
214
- type: 'moveend',
215
- zoom: this.map.getView().getZoom(),
216
- coordinate: this.map.getView().getCenter()
217
- };
218
- this.triggerListeners('moveend', eventData);
219
- }
220
- /**
221
- * 处理缩放结束事件
222
- */
223
- handleZoomEndEvent() {
224
- const eventData = {
225
- type: 'zoomend',
226
- zoom: this.map.getView().getZoom(),
227
- coordinate: this.map.getView().getCenter()
228
- };
229
- this.triggerListeners('zoomend', eventData);
230
- }
231
- /**
232
- * 处理渲染完成事件
233
- */
234
- handleRenderCompleteEvent() {
235
- const eventData = {
236
- type: 'rendercomplete',
237
- zoom: this.map.getView().getZoom(),
238
- coordinate: this.map.getView().getCenter()
239
- };
240
- this.triggerListeners('rendercomplete', eventData);
241
- }
242
- /**
243
- * 处理错误事件
244
- * @param error 错误对象
245
- */
246
- handleErrorEvent(error) {
247
- const eventData = {
248
- type: 'error',
249
- originalEvent: error,
250
- error: error
251
- };
252
- this.triggerListeners('error', eventData);
253
- }
254
- /**
255
- * 创建事件数据
256
- * @param type 事件类型
257
- * @param event 原始事件
258
- */
259
- createEventData(type, event) {
260
- const pixel = this.map.getEventPixel(event.originalEvent);
261
- const features = this.map.getFeaturesAtPixel(pixel);
262
- return {
263
- type,
264
- originalEvent: event.originalEvent,
265
- coordinate: event.coordinate,
266
- pixel,
267
- features,
268
- feature: features.length > 0 ? features[0] : undefined
269
- };
270
- }
271
- /**
272
- * 触发监听器
273
- * @param type 事件类型
274
- * @param eventData 事件数据
275
- */
276
- triggerListeners(type, eventData) {
277
- const typeListeners = [];
278
- this.listeners.forEach((listener) => {
279
- if (listener.type === type) {
280
- typeListeners.push(listener);
281
- }
282
- });
283
- typeListeners.forEach((listener) => {
284
- try {
285
- // 应用过滤器
286
- if (listener.options?.filter && !listener.options.filter(eventData)) {
287
- return;
288
- }
289
- // 执行回调
290
- listener.callback(eventData);
291
- // 如果是一次性监听器,移除它
292
- if (listener.options?.once) {
293
- this.off(listener.id);
294
- }
295
- }
296
- catch (error) {
297
- ErrorHandler.getInstance().createAndHandleError(`Error in event listener: ${error}`, ErrorType.COMPONENT_ERROR, { listener, eventData, error });
298
- }
299
- });
300
- }
301
- /**
302
- * 获取监听器信息(用于调试)
303
- */
304
- getListenersInfo() {
305
- const result = [];
306
- this.listeners.forEach((listener) => {
307
- result.push({
308
- id: listener.id,
309
- type: listener.type,
310
- hasFilter: !!listener.options?.filter,
311
- isOnce: !!listener.options?.once
312
- });
313
- });
314
- return result;
315
- }
316
- }
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
+ this.mapEventListeners = new Map();
15
+ ErrorHandler.validateMap(map);
16
+ this.map = map;
17
+ this.initializeEventCounters();
18
+ }
19
+ /**
20
+ * 初始化事件计数器
21
+ */
22
+ initializeEventCounters() {
23
+ const eventTypes = ['click', 'dblclick', 'hover', 'moveend', 'zoomend', 'pointermove', 'rendercomplete', 'error'];
24
+ eventTypes.forEach(type => {
25
+ this.eventCounters.set(type, 0);
26
+ });
27
+ }
28
+ /**
29
+ * 注册事件监听器
30
+ * @param type 事件类型
31
+ * @param callback 回调函数
32
+ * @param options 选项
33
+ * @returns 事件监听器ID
34
+ */
35
+ on(type, callback, options) {
36
+ ErrorHandler.validate(typeof callback === 'function', 'Event callback must be a function', { type, callback });
37
+ const id = this.generateListenerId(type);
38
+ const listener = {
39
+ id,
40
+ type,
41
+ callback,
42
+ options
43
+ };
44
+ this.listeners.set(id, listener);
45
+ this.attachMapEvent(type);
46
+ return id;
47
+ }
48
+ /**
49
+ * 移除事件监听器
50
+ * @param id 监听器ID
51
+ */
52
+ off(id) {
53
+ const listener = this.listeners.get(id);
54
+ if (!listener) {
55
+ return false;
56
+ }
57
+ this.listeners.delete(id);
58
+ // 如果该类型没有其他监听器了,移除地图事件监听器
59
+ const remainingListeners = this.getListenerCount(listener.type);
60
+ if (remainingListeners === 0) {
61
+ this.detachMapEvent(listener.type);
62
+ }
63
+ return true;
64
+ }
65
+ /**
66
+ * 移除指定类型的所有事件监听器
67
+ * @param type 事件类型
68
+ */
69
+ offAll(type) {
70
+ const idsToRemove = [];
71
+ this.listeners.forEach((listener, id) => {
72
+ if (listener.type === type) {
73
+ idsToRemove.push(id);
74
+ }
75
+ });
76
+ idsToRemove.forEach(id => {
77
+ this.listeners.delete(id);
78
+ });
79
+ // 移除对应的地图事件监听器
80
+ if (idsToRemove.length > 0) {
81
+ this.detachMapEvent(type);
82
+ }
83
+ }
84
+ /**
85
+ * 清除所有事件监听器
86
+ */
87
+ clear() {
88
+ this.listeners.clear();
89
+ // 移除所有地图事件监听器
90
+ this.mapEventListeners.forEach((_, type) => {
91
+ this.detachMapEvent(type);
92
+ });
93
+ }
94
+ /**
95
+ * 获取指定类型的监听器数量
96
+ * @param type 事件类型
97
+ */
98
+ getListenerCount(type) {
99
+ let count = 0;
100
+ this.listeners.forEach((listener) => {
101
+ if (listener.type === type) {
102
+ count++;
103
+ }
104
+ });
105
+ return count;
106
+ }
107
+ /**
108
+ * 生成监听器ID
109
+ * @param type 事件类型
110
+ */
111
+ generateListenerId(type) {
112
+ const counter = this.eventCounters.get(type) || 0;
113
+ this.eventCounters.set(type, counter + 1);
114
+ return `${type}_${counter + 1}_${Date.now()}`;
115
+ }
116
+ /**
117
+ * 附加地图事件
118
+ * @param type 事件类型
119
+ */
120
+ attachMapEvent(type) {
121
+ const existingListeners = this.getListenerCount(type);
122
+ if (existingListeners > 1) {
123
+ return; // 已经附加过该类型的事件
124
+ }
125
+ // 如果已经有地图事件监听器,先移除
126
+ if (this.mapEventListeners.has(type)) {
127
+ this.detachMapEvent(type);
128
+ }
129
+ let eventHandler;
130
+ let target = this.map;
131
+ let eventName;
132
+ switch (type) {
133
+ case 'click':
134
+ eventHandler = this.handleClickEvent.bind(this);
135
+ eventName = 'click';
136
+ break;
137
+ case 'dblclick':
138
+ eventHandler = this.handleDblClickEvent.bind(this);
139
+ eventName = 'dblclick';
140
+ break;
141
+ case 'hover':
142
+ case 'pointermove':
143
+ eventHandler = this.handlePointerMoveEvent.bind(this);
144
+ eventName = 'pointermove';
145
+ break;
146
+ case 'moveend':
147
+ eventHandler = this.handleMoveEndEvent.bind(this);
148
+ eventName = 'moveend';
149
+ break;
150
+ case 'zoomend':
151
+ eventHandler = this.handleZoomEndEvent.bind(this);
152
+ target = this.map.getView();
153
+ eventName = 'change:resolution';
154
+ break;
155
+ case 'rendercomplete':
156
+ eventHandler = this.handleRenderCompleteEvent.bind(this);
157
+ eventName = 'rendercomplete';
158
+ this.map.once(eventName, eventHandler);
159
+ this.mapEventListeners.set(type, { handler: eventHandler, target, eventName, isOnce: true });
160
+ return;
161
+ case 'error':
162
+ eventHandler = this.handleErrorEvent.bind(this);
163
+ eventName = 'error';
164
+ break;
165
+ default:
166
+ return;
167
+ }
168
+ target.on(eventName, eventHandler);
169
+ this.mapEventListeners.set(type, { handler: eventHandler, target, eventName, isOnce: false });
170
+ }
171
+ /**
172
+ * 移除地图事件监听器
173
+ * @param type 事件类型
174
+ */
175
+ detachMapEvent(type) {
176
+ const mapListener = this.mapEventListeners.get(type);
177
+ if (!mapListener) {
178
+ return;
179
+ }
180
+ const { handler, target, eventName } = mapListener;
181
+ target.un(eventName, handler);
182
+ this.mapEventListeners.delete(type);
183
+ }
184
+ /**
185
+ * 处理点击事件
186
+ * @param event 地图浏览器事件
187
+ */
188
+ handleClickEvent(event) {
189
+ const eventData = this.createEventData('click', event);
190
+ this.triggerListeners('click', eventData);
191
+ }
192
+ /**
193
+ * 处理双击事件
194
+ * @param event 地图浏览器事件
195
+ */
196
+ handleDblClickEvent(event) {
197
+ const eventData = this.createEventData('dblclick', event);
198
+ this.triggerListeners('dblclick', eventData);
199
+ }
200
+ /**
201
+ * 处理指针移动事件
202
+ * @param event 地图浏览器事件
203
+ */
204
+ handlePointerMoveEvent(event) {
205
+ const eventData = this.createEventData('pointermove', event);
206
+ this.triggerListeners('hover', eventData);
207
+ this.triggerListeners('pointermove', eventData);
208
+ }
209
+ /**
210
+ * 处理移动结束事件
211
+ */
212
+ handleMoveEndEvent() {
213
+ const eventData = {
214
+ type: 'moveend',
215
+ zoom: this.map.getView().getZoom(),
216
+ coordinate: this.map.getView().getCenter()
217
+ };
218
+ this.triggerListeners('moveend', eventData);
219
+ }
220
+ /**
221
+ * 处理缩放结束事件
222
+ */
223
+ handleZoomEndEvent() {
224
+ const eventData = {
225
+ type: 'zoomend',
226
+ zoom: this.map.getView().getZoom(),
227
+ coordinate: this.map.getView().getCenter()
228
+ };
229
+ this.triggerListeners('zoomend', eventData);
230
+ }
231
+ /**
232
+ * 处理渲染完成事件
233
+ */
234
+ handleRenderCompleteEvent() {
235
+ const eventData = {
236
+ type: 'rendercomplete',
237
+ zoom: this.map.getView().getZoom(),
238
+ coordinate: this.map.getView().getCenter()
239
+ };
240
+ this.triggerListeners('rendercomplete', eventData);
241
+ }
242
+ /**
243
+ * 处理错误事件
244
+ * @param error 错误对象
245
+ */
246
+ handleErrorEvent(error) {
247
+ const eventData = {
248
+ type: 'error',
249
+ originalEvent: error,
250
+ error: error
251
+ };
252
+ this.triggerListeners('error', eventData);
253
+ }
254
+ /**
255
+ * 创建事件数据
256
+ * @param type 事件类型
257
+ * @param event 原始事件
258
+ */
259
+ createEventData(type, event) {
260
+ const pixel = this.map.getEventPixel(event.originalEvent);
261
+ const features = this.map.getFeaturesAtPixel(pixel);
262
+ return {
263
+ type,
264
+ originalEvent: event.originalEvent,
265
+ coordinate: event.coordinate,
266
+ pixel,
267
+ features,
268
+ feature: features.length > 0 ? features[0] : undefined
269
+ };
270
+ }
271
+ /**
272
+ * 触发监听器
273
+ * @param type 事件类型
274
+ * @param eventData 事件数据
275
+ */
276
+ triggerListeners(type, eventData) {
277
+ const typeListeners = [];
278
+ this.listeners.forEach((listener) => {
279
+ if (listener.type === type) {
280
+ typeListeners.push(listener);
281
+ }
282
+ });
283
+ typeListeners.forEach((listener) => {
284
+ try {
285
+ // 应用过滤器
286
+ if (listener.options?.filter && !listener.options.filter(eventData)) {
287
+ return;
288
+ }
289
+ // 执行回调
290
+ listener.callback(eventData);
291
+ // 如果是一次性监听器,移除它
292
+ if (listener.options?.once) {
293
+ this.off(listener.id);
294
+ }
295
+ }
296
+ catch (error) {
297
+ ErrorHandler.getInstance().createAndHandleError(`Error in event listener: ${error}`, ErrorType.COMPONENT_ERROR, { listener, eventData, error });
298
+ }
299
+ });
300
+ }
301
+ /**
302
+ * 获取监听器信息(用于调试)
303
+ */
304
+ getListenersInfo() {
305
+ const result = [];
306
+ this.listeners.forEach((listener) => {
307
+ result.push({
308
+ id: listener.id,
309
+ type: listener.type,
310
+ hasFilter: !!listener.options?.filter,
311
+ isOnce: !!listener.options?.once
312
+ });
313
+ });
314
+ return result;
315
+ }
316
+ }