0
# Events System
1
2
Comprehensive event handling system providing map interactions, property changes, and lifecycle events with support for custom event listeners and conditions.
3
4
## Capabilities
5
6
### Core Event Classes
7
8
Foundation classes for the OpenLayers event system.
9
10
```typescript { .api }
11
/**
12
* Base event class
13
*/
14
class BaseEvent {
15
constructor(type: string);
16
17
/** Event type string */
18
type: string;
19
/** Target object that fired the event */
20
target: any;
21
/** Whether default action is prevented */
22
defaultPrevented: boolean;
23
24
/** Prevent default action */
25
preventDefault(): void;
26
/** Stop event propagation */
27
stopPropagation(): void;
28
}
29
30
/**
31
* Map-specific event
32
*/
33
class MapEvent extends BaseEvent {
34
constructor(type: string, map: Map, frameState?: FrameState);
35
36
/** Map that fired the event */
37
map: Map;
38
/** Frame state at event time */
39
frameState?: FrameState;
40
}
41
42
/**
43
* Map browser event (user interactions)
44
*/
45
class MapBrowserEvent extends MapEvent {
46
constructor(type: string, map: Map, originalEvent: Event, dragging?: boolean, frameState?: FrameState);
47
48
/** Original browser event */
49
originalEvent: Event;
50
/** Pixel coordinates */
51
pixel: Pixel;
52
/** Map coordinates */
53
coordinate: Coordinate;
54
/** Whether currently dragging */
55
dragging: boolean;
56
}
57
58
/**
59
* Event target implementation
60
*/
61
class Target {
62
constructor();
63
64
/** Add event listener */
65
addEventListener(type: string, listener: (event: Event) => void): void;
66
/** Remove event listener */
67
removeEventListener(type: string, listener: (event: Event) => void): void;
68
/** Dispatch event */
69
dispatchEvent(event: Event | string): boolean;
70
}
71
```
72
73
### Event Registration Functions
74
75
Core functions for managing event listeners.
76
77
```typescript { .api }
78
/**
79
* Register event listener and return key for removal
80
* @param target - Event target
81
* @param type - Event type
82
* @param listener - Event listener function
83
* @param thisArg - Context for listener
84
*/
85
function listen(target: EventTarget, type: string, listener: ListenerFunction, thisArg?: Object): EventsKey;
86
87
/**
88
* Register one-time event listener
89
* @param target - Event target
90
* @param type - Event type
91
* @param listener - Event listener function
92
* @param thisArg - Context for listener
93
*/
94
function listenOnce(target: EventTarget, type: string, listener: ListenerFunction, thisArg?: Object): EventsKey;
95
96
/**
97
* Unregister event listener using key
98
* @param key - Event key returned from listen/listenOnce
99
*/
100
function unlistenByKey(key: EventsKey | EventsKey[]): void;
101
102
/**
103
* Unregister event listener by function
104
* @param target - Event target
105
* @param type - Event type
106
* @param listener - Event listener function
107
* @param thisArg - Context for listener
108
*/
109
function unlisten(target: EventTarget, type: string, listener: ListenerFunction, thisArg?: Object): void;
110
```
111
112
**Usage Examples:**
113
114
```typescript
115
import { listen, listenOnce, unlistenByKey } from 'ol/events';
116
import Map from 'ol/Map';
117
118
// Listen for map clicks
119
const map = new Map({...});
120
const clickKey = listen(map, 'click', (event) => {
121
console.log('Map clicked at:', event.coordinate);
122
});
123
124
// One-time listener
125
const loadKey = listenOnce(map, 'loadend', () => {
126
console.log('Map finished loading');
127
});
128
129
// Remove listener
130
unlistenByKey(clickKey);
131
132
// Multiple listeners
133
const keys = [
134
listen(map, 'movestart', onMoveStart),
135
listen(map, 'moveend', onMoveEnd)
136
];
137
138
// Remove all listeners
139
unlistenByKey(keys);
140
```
141
142
### Map Events
143
144
Events specific to map lifecycle and interactions.
145
146
```typescript { .api }
147
/** Map event types */
148
const MapEventType = {
149
/** Fired after map rendering */
150
POSTRENDER: 'postrender',
151
/** Fired when map starts moving */
152
MOVESTART: 'movestart',
153
/** Fired when map stops moving */
154
MOVEEND: 'moveend',
155
/** Fired when loading starts */
156
LOADSTART: 'loadstart',
157
/** Fired when loading ends */
158
LOADEND: 'loadend'
159
} as const;
160
161
/** Map browser event types */
162
const MapBrowserEventType = {
163
/** Single click event */
164
SINGLECLICK: 'singleclick',
165
/** Click event (includes double-clicks) */
166
CLICK: 'click',
167
/** Double click event */
168
DBLCLICK: 'dblclick',
169
/** Pointer drag event */
170
POINTERDRAG: 'pointerdrag',
171
/** Pointer move event */
172
POINTERMOVE: 'pointermove',
173
/** Pointer down event */
174
POINTERDOWN: 'pointerdown',
175
/** Pointer up event */
176
POINTERUP: 'pointerup',
177
/** Pointer over event */
178
POINTEROVER: 'pointerover',
179
/** Pointer out event */
180
POINTEROUT: 'pointerout',
181
/** Pointer enter event */
182
POINTERENTER: 'pointerenter',
183
/** Pointer leave event */
184
POINTERLEAVE: 'pointerleave',
185
/** Pointer cancel event */
186
POINTERCANCEL: 'pointercancel'
187
} as const;
188
```
189
190
**Usage Examples:**
191
192
```typescript
193
import Map from 'ol/Map';
194
195
const map = new Map({...});
196
197
// Map lifecycle events
198
map.on('loadstart', () => {
199
console.log('Map loading started');
200
});
201
202
map.on('loadend', () => {
203
console.log('Map loading finished');
204
});
205
206
map.on('movestart', (event) => {
207
console.log('Map started moving');
208
});
209
210
map.on('moveend', (event) => {
211
console.log('Map stopped moving');
212
console.log('New center:', map.getView().getCenter());
213
});
214
215
// Browser interaction events
216
map.on('singleclick', (event) => {
217
console.log('Single click at:', event.coordinate);
218
});
219
220
map.on('pointermove', (event) => {
221
// Mouse/touch move
222
const pixel = event.pixel;
223
const hit = map.hasFeatureAtPixel(pixel);
224
map.getTargetElement().style.cursor = hit ? 'pointer' : '';
225
});
226
227
map.on('dblclick', (event) => {
228
console.log('Double click - zoom in');
229
});
230
```
231
232
### Observable Class Methods
233
234
Enhanced event handling for OpenLayers objects.
235
236
```typescript { .api }
237
/**
238
* Observable class with convenient event methods
239
*/
240
class Observable extends Target {
241
constructor();
242
243
/** Add event listener (alias for addEventListener) */
244
on(type: string | string[], listener: (event: BaseEvent) => void): EventsKey | EventsKey[];
245
246
/** Add one-time event listener */
247
once(type: string | string[], listener: (event: BaseEvent) => void): EventsKey | EventsKey[];
248
249
/** Remove event listener */
250
un(type: string | string[], listener: (event: BaseEvent) => void): void;
251
252
/** Fire/dispatch an event */
253
dispatchEvent(event: BaseEvent | string): boolean;
254
255
/** Get revision number (incremented on changes) */
256
getRevision(): number;
257
258
/** Increment revision (trigger change event) */
259
changed(): void;
260
}
261
```
262
263
**Usage Examples:**
264
265
```typescript
266
import VectorSource from 'ol/source/Vector';
267
import Feature from 'ol/Feature';
268
269
const vectorSource = new VectorSource();
270
271
// Listen for feature changes
272
vectorSource.on('addfeature', (event) => {
273
console.log('Feature added:', event.feature);
274
});
275
276
vectorSource.on('removefeature', (event) => {
277
console.log('Feature removed:', event.feature);
278
});
279
280
vectorSource.on('changefeature', (event) => {
281
console.log('Feature changed:', event.feature);
282
});
283
284
// One-time listener
285
vectorSource.once('clear', () => {
286
console.log('Source cleared');
287
});
288
289
// Multiple event types
290
const keys = vectorSource.on(['addfeature', 'removefeature'], (event) => {
291
console.log('Feature collection changed');
292
});
293
```
294
295
### Property Change Events
296
297
Events for object property modifications.
298
299
```typescript { .api }
300
/** Object event types */
301
const ObjectEventType = {
302
/** Property change event */
303
PROPERTYCHANGE: 'propertychange'
304
} as const;
305
306
/**
307
* Property change event
308
*/
309
class ObjectEvent extends BaseEvent {
310
constructor(type: string, key: string, oldValue: any);
311
312
/** Property key that changed */
313
key: string;
314
/** Previous property value */
315
oldValue: any;
316
}
317
```
318
319
**Usage Examples:**
320
321
```typescript
322
import View from 'ol/View';
323
324
const view = new View({
325
center: [0, 0],
326
zoom: 2
327
});
328
329
// Listen for view property changes
330
view.on('propertychange', (event) => {
331
console.log(`Property "${event.key}" changed from`, event.oldValue, 'to', view.get(event.key));
332
});
333
334
// Listen for specific properties
335
view.on('change:center', () => {
336
console.log('Center changed to:', view.getCenter());
337
});
338
339
view.on('change:zoom', () => {
340
console.log('Zoom changed to:', view.getZoom());
341
});
342
343
view.on('change:rotation', () => {
344
console.log('Rotation changed to:', view.getRotation());
345
});
346
347
// Change properties to trigger events
348
view.setCenter([100, 100]);
349
view.setZoom(5);
350
```
351
352
### Collection Events
353
354
Events for collection modifications (adding/removing items).
355
356
```typescript { .api }
357
/** Collection event types */
358
const CollectionEventType = {
359
/** Item added to collection */
360
ADD: 'add',
361
/** Item removed from collection */
362
REMOVE: 'remove'
363
} as const;
364
365
/**
366
* Collection event
367
*/
368
class CollectionEvent extends BaseEvent {
369
constructor(type: string, element: any, index?: number);
370
371
/** Element that was added/removed */
372
element: any;
373
/** Index of the element */
374
index?: number;
375
}
376
```
377
378
**Usage Examples:**
379
380
```typescript
381
import Collection from 'ol/Collection';
382
import Feature from 'ol/Feature';
383
384
const collection = new Collection();
385
386
// Listen for collection changes
387
collection.on('add', (event) => {
388
console.log('Item added at index', event.index, ':', event.element);
389
});
390
391
collection.on('remove', (event) => {
392
console.log('Item removed from index', event.index, ':', event.element);
393
});
394
395
// Add items to trigger events
396
const feature1 = new Feature();
397
const feature2 = new Feature();
398
399
collection.push(feature1);
400
collection.insertAt(0, feature2);
401
collection.remove(feature1);
402
```
403
404
### Render Events
405
406
Events during the rendering process.
407
408
```typescript { .api }
409
/**
410
* Render event fired during map rendering
411
*/
412
class RenderEvent extends BaseEvent {
413
constructor(type: string, vectorContext?: VectorContext, frameState?: FrameState, context?: CanvasRenderingContext2D, glContext?: WebGLRenderingContext);
414
415
/** Vector context for immediate rendering */
416
vectorContext?: VectorContext;
417
/** Current frame state */
418
frameState?: FrameState;
419
/** 2D canvas context */
420
context?: CanvasRenderingContext2D;
421
/** WebGL context */
422
glContext?: WebGLRenderingContext;
423
}
424
```
425
426
**Usage Examples:**
427
428
```typescript
429
import VectorLayer from 'ol/layer/Vector';
430
import { Style, Circle, Fill } from 'ol/style';
431
432
const vectorLayer = new VectorLayer({...});
433
434
// Listen for layer rendering
435
vectorLayer.on('prerender', (event) => {
436
// Before layer renders
437
console.log('Layer about to render');
438
});
439
440
vectorLayer.on('postrender', (event) => {
441
// After layer renders - can draw additional content
442
const vectorContext = event.vectorContext;
443
const frameState = event.frameState;
444
445
// Draw custom overlay graphics
446
vectorContext.setStyle(new Style({
447
image: new Circle({
448
radius: 5,
449
fill: new Fill({ color: 'red' })
450
})
451
}));
452
453
vectorContext.drawGeometry(customGeometry);
454
});
455
456
// Map-level render events
457
map.on('postrender', (event) => {
458
// After entire map renders
459
console.log('Map render complete');
460
});
461
```
462
463
### Event Conditions
464
465
Predefined functions for testing event conditions in interactions.
466
467
```typescript { .api }
468
/** Event condition function type */
469
type EventCondition = (event: MapBrowserEvent) => boolean;
470
471
/** Always return true */
472
const always: EventCondition;
473
474
/** Always return false */
475
const never: EventCondition;
476
477
/** Test for single click */
478
const singleClick: EventCondition;
479
480
/** Test for double click */
481
const doubleClick: EventCondition;
482
483
/** Test for no modifier keys */
484
const noModifierKeys: EventCondition;
485
486
/** Test for platform modifier key only (Cmd/Ctrl) */
487
const platformModifierKeyOnly: EventCondition;
488
489
/** Test for shift key only */
490
const shiftKeyOnly: EventCondition;
491
492
/** Test for alt key only */
493
const altKeyOnly: EventCondition;
494
495
/** Test for pointer move */
496
const pointerMove: EventCondition;
497
498
/** Test for primary action (left button/touch) */
499
const primaryAction: EventCondition;
500
501
/** Test that target element is not editable */
502
const targetNotEditable: EventCondition;
503
```
504
505
**Usage Examples:**
506
507
```typescript
508
import { Select } from 'ol/interaction';
509
import { click, platformModifierKeyOnly, shiftKeyOnly } from 'ol/events/condition';
510
511
// Use conditions in interactions
512
const selectInteraction = new Select({
513
condition: click, // Only on click
514
addCondition: shiftKeyOnly, // Shift+click to add to selection
515
removeCondition: platformModifierKeyOnly, // Ctrl/Cmd+click to remove
516
});
517
518
// Custom condition function
519
const customCondition = (event) => {
520
return event.originalEvent.button === 0 && // Left mouse button
521
!event.originalEvent.altKey && // No alt key
522
event.pixel[0] > 100; // X coordinate > 100
523
};
524
525
const customSelect = new Select({
526
condition: customCondition
527
});
528
```
529
530
## Types
531
532
```typescript { .api }
533
type EventsKey = {
534
target: EventTarget;
535
type: string;
536
listener: ListenerFunction;
537
};
538
539
type ListenerFunction = (event: Event | BaseEvent) => void;
540
type Pixel = [number, number];
541
type Coordinate = [number, number] | [number, number, number] | [number, number, number, number];
542
543
interface FrameState {
544
time: number;
545
viewState: ViewState;
546
animate: boolean;
547
coordinateToPixelTransform: Transform;
548
extent: Extent;
549
focus?: Coordinate;
550
index: number;
551
layerStatesArray: LayerState[];
552
layerIndex: number;
553
pixelRatio: number;
554
pixelToCoordinateTransform: Transform;
555
postRenderFunctions: PostRenderFunction[];
556
size: Size;
557
tileQueue: TileQueue;
558
usedTiles: Object<string, Object<string, boolean>>;
559
viewHints: number[];
560
wantedTiles: Object<string, Object<string, boolean>>;
561
}
562
```