0
# Events and Interactions
1
2
Complete event system for handling user interactions, plot updates, and custom behaviors.
3
4
## Capabilities
5
6
### Event Management
7
8
Methods for adding, removing, and managing event listeners on plots.
9
10
```javascript { .api }
11
/**
12
* Event listener management methods
13
*/
14
interface EventMethods {
15
/**
16
* Add event listener to plot
17
* @param event - Event name
18
* @param handler - Event handler function
19
*/
20
on(event: string, handler: Function): void;
21
22
/**
23
* Add one-time event listener
24
* @param event - Event name
25
* @param handler - Event handler function that will be called only once
26
*/
27
once(event: string, handler: Function): void;
28
29
/**
30
* Remove specific event listener
31
* @param event - Event name
32
* @param handler - Specific handler function to remove
33
*/
34
removeListener(event: string, handler: Function): void;
35
36
/**
37
* Remove all listeners for a specific event
38
* @param event - Event name
39
*/
40
removeAllListeners(event: string): void;
41
42
/**
43
* Emit/trigger an event
44
* @param event - Event name
45
* @param data - Event data to pass to handlers
46
*/
47
emit(event: string, data?: any): void;
48
}
49
```
50
51
**Usage Examples:**
52
53
```javascript
54
// Add event listener
55
const myDiv = document.getElementById('myDiv');
56
57
myDiv.on('plotly_click', function(data) {
58
console.log('Plot clicked:', data);
59
});
60
61
// One-time listener
62
myDiv.once('plotly_afterplot', function() {
63
console.log('Plot created for the first time');
64
});
65
66
// Remove specific listener
67
function clickHandler(data) {
68
console.log('Clicked:', data);
69
}
70
myDiv.on('plotly_click', clickHandler);
71
myDiv.removeListener('plotly_click', clickHandler);
72
73
// Remove all listeners for an event
74
myDiv.removeAllListeners('plotly_hover');
75
```
76
77
### Plot Lifecycle Events
78
79
Events that fire during plot creation, updates, and destruction.
80
81
```javascript { .api }
82
/**
83
* Plot lifecycle event names and their data structures
84
*/
85
interface PlotLifecycleEvents {
86
'plotly_beforeplot': {};
87
'plotly_afterplot': {};
88
'plotly_redraw': {};
89
'plotly_restyle': {
90
data: any[];
91
traces: number[];
92
};
93
'plotly_relayout': {
94
layout: Partial<Layout>;
95
};
96
'plotly_update': {
97
data: any[];
98
layout: Partial<Layout>;
99
traces: number[];
100
};
101
'plotly_react': {
102
data: any[];
103
layout: Partial<Layout>;
104
};
105
'plotly_framework': any;
106
'plotly_purge': {};
107
}
108
```
109
110
**Usage Examples:**
111
112
```javascript
113
// Listen for plot creation
114
myDiv.on('plotly_afterplot', function() {
115
console.log('Plot has been created');
116
// Initialize any custom behaviors
117
});
118
119
// Listen for restyle events
120
myDiv.on('plotly_restyle', function(eventData) {
121
console.log('Traces restyled:', eventData.traces);
122
console.log('Update data:', eventData.data);
123
});
124
125
// Listen for layout changes
126
myDiv.on('plotly_relayout', function(eventData) {
127
console.log('Layout updated:', eventData.layout);
128
if (eventData.layout['xaxis.range']) {
129
console.log('X-axis range changed');
130
}
131
});
132
133
// Listen for combined updates
134
myDiv.on('plotly_update', function(eventData) {
135
console.log('Plot updated');
136
console.log('Data changes:', eventData.data);
137
console.log('Layout changes:', eventData.layout);
138
});
139
```
140
141
### User Interaction Events
142
143
Events triggered by user interactions with the plot.
144
145
```javascript { .api }
146
/**
147
* User interaction event data structures
148
*/
149
interface InteractionEvents {
150
'plotly_click': {
151
points: PlotlyClickPoint[];
152
event: MouseEvent;
153
};
154
'plotly_hover': {
155
points: PlotlyHoverPoint[];
156
event: MouseEvent;
157
xpx: number;
158
ypx: number;
159
};
160
'plotly_unhover': {
161
points: PlotlyHoverPoint[];
162
event: MouseEvent;
163
};
164
'plotly_selected': {
165
points: PlotlySelectedPoint[];
166
selection?: SelectionRange;
167
};
168
'plotly_deselect': {};
169
'plotly_brushing': {
170
range: BrushRange;
171
};
172
'plotly_brushed': {
173
range: BrushRange;
174
};
175
'plotly_doubleclick': {};
176
'plotly_zoom': {};
177
'plotly_pan': {};
178
}
179
180
interface PlotlyClickPoint {
181
curveNumber: number;
182
pointNumber: number | number[];
183
pointIndex: number;
184
x: any;
185
y: any;
186
z?: any;
187
data: any;
188
fullData: any;
189
xaxis: any;
190
yaxis: any;
191
}
192
193
interface PlotlyHoverPoint extends PlotlyClickPoint {
194
bbox: {
195
x0: number;
196
x1: number;
197
y0: number;
198
y1: number;
199
};
200
distance: number;
201
}
202
203
interface PlotlySelectedPoint extends PlotlyClickPoint {
204
selected?: boolean;
205
}
206
207
interface SelectionRange {
208
x: [number, number];
209
y: [number, number];
210
}
211
212
interface BrushRange {
213
x: [number, number];
214
y: [number, number];
215
}
216
```
217
218
**Usage Examples:**
219
220
```javascript
221
// Handle click events
222
myDiv.on('plotly_click', function(data) {
223
const point = data.points[0];
224
console.log('Clicked point:', {
225
trace: point.curveNumber,
226
index: point.pointNumber,
227
x: point.x,
228
y: point.y
229
});
230
231
// Highlight clicked point
232
Plotly.restyle(myDiv, {
233
'marker.color': 'red'
234
}, [point.curveNumber]);
235
});
236
237
// Handle hover events
238
myDiv.on('plotly_hover', function(data) {
239
const point = data.points[0];
240
console.log('Hovering over:', point.x, point.y);
241
242
// Update external display
243
document.getElementById('info').innerHTML =
244
`Value: ${point.y} at ${point.x}`;
245
});
246
247
myDiv.on('plotly_unhover', function() {
248
document.getElementById('info').innerHTML = '';
249
});
250
251
// Handle selection events
252
myDiv.on('plotly_selected', function(data) {
253
console.log('Selected points:', data.points.length);
254
255
if (data.points.length > 0) {
256
const selectedData = data.points.map(pt => ({
257
x: pt.x,
258
y: pt.y,
259
trace: pt.curveNumber
260
}));
261
console.log('Selected data:', selectedData);
262
}
263
});
264
265
// Handle brush selection
266
myDiv.on('plotly_brushed', function(data) {
267
console.log('Brushed area:', data.range);
268
269
// Filter data in another chart based on selection
270
const xRange = data.range.x;
271
const yRange = data.range.y;
272
273
// Update related visualization
274
updateSecondaryChart(xRange, yRange);
275
});
276
```
277
278
### Animation Events
279
280
Events related to plot animations and frame transitions.
281
282
```javascript { .api }
283
/**
284
* Animation event data structures
285
*/
286
interface AnimationEvents {
287
'plotly_animating': {};
288
'plotly_animatingframe': {
289
frame: any;
290
animation: any;
291
};
292
'plotly_animated': {};
293
'plotly_animationinterrupted': {};
294
}
295
```
296
297
**Usage Examples:**
298
299
```javascript
300
// Track animation progress
301
myDiv.on('plotly_animating', function() {
302
console.log('Animation started');
303
document.getElementById('status').innerHTML = 'Animating...';
304
});
305
306
myDiv.on('plotly_animatingframe', function(data) {
307
console.log('Frame:', data.frame.name);
308
});
309
310
myDiv.on('plotly_animated', function() {
311
console.log('Animation completed');
312
document.getElementById('status').innerHTML = 'Complete';
313
});
314
315
// Handle interrupted animations
316
myDiv.on('plotly_animationinterrupted', function() {
317
console.log('Animation was interrupted');
318
document.getElementById('status').innerHTML = 'Interrupted';
319
});
320
```
321
322
### Programmatic Hover and Interaction
323
324
Methods for triggering hover effects and interactions programmatically.
325
326
```javascript { .api }
327
/**
328
* Programmatic interaction methods
329
*/
330
interface ProgrammaticInteractions {
331
/**
332
* Trigger hover effect on specific points
333
* @param gd - Graph div element
334
* @param hoverData - Array of points to hover over
335
* @param hoverOpts - Hover options and styling
336
*/
337
hover(gd: any, hoverData: HoverData[], hoverOpts?: HoverOptions): void;
338
339
/**
340
* Clear all hover effects
341
* @param gd - Graph div element
342
*/
343
unhover(gd: any): void;
344
345
/**
346
* Create standalone hover box (not attached to plot)
347
* @param hoverData - Hover data for the box
348
* @param opts - Positioning and styling options
349
*/
350
loneHover(hoverData: HoverData, opts: LoneHoverOptions): HTMLElement;
351
352
/**
353
* Remove standalone hover box
354
* @param container - Container element with hover box
355
*/
356
loneUnhover(container: HTMLElement): void;
357
}
358
359
interface HoverData {
360
curveNumber: number;
361
pointNumber: number;
362
x?: any;
363
y?: any;
364
z?: any;
365
}
366
367
interface HoverOptions {
368
xpx?: number;
369
ypx?: number;
370
hovermode?: 'closest' | 'x' | 'y' | 'x unified' | 'y unified';
371
}
372
373
interface LoneHoverOptions {
374
container: HTMLElement;
375
x0: number;
376
x1: number;
377
y0: number;
378
y1: number;
379
anchorX?: number;
380
anchorY?: number;
381
colorIndex?: number;
382
}
383
```
384
385
**Usage Examples:**
386
387
```javascript
388
// Programmatically trigger hover
389
function highlightPoint(traceIndex, pointIndex) {
390
Plotly.Fx.hover(myDiv, [{
391
curveNumber: traceIndex,
392
pointNumber: pointIndex
393
}]);
394
}
395
396
// Clear hover
397
function clearHighlight() {
398
Plotly.Fx.unhover(myDiv);
399
}
400
401
// Create standalone hover box
402
function showCustomTooltip(x, y, text) {
403
const container = document.getElementById('tooltip-container');
404
405
Plotly.Fx.loneHover({
406
x: x,
407
y: y,
408
text: text,
409
color: 'blue'
410
}, {
411
container: container,
412
x0: 100,
413
x1: 200,
414
y0: 50,
415
y1: 100
416
});
417
}
418
419
// Remove standalone hover
420
function hideCustomTooltip() {
421
const container = document.getElementById('tooltip-container');
422
Plotly.Fx.loneUnhover(container);
423
}
424
```
425
426
### Custom Event Handlers
427
428
Examples of common event handling patterns and custom behaviors.
429
430
**Usage Examples:**
431
432
```javascript
433
// Cross-filter pattern - link multiple charts
434
function linkCharts(chart1, chart2) {
435
chart1.on('plotly_selected', function(data) {
436
if (data.points.length > 0) {
437
const selectedIds = data.points.map(pt => pt.customdata);
438
439
// Filter second chart based on selection
440
const filteredTrace = filterTraceByIds(chart2Data, selectedIds);
441
Plotly.react(chart2, [filteredTrace], chart2Layout);
442
}
443
});
444
445
chart1.on('plotly_deselect', function() {
446
// Reset second chart
447
Plotly.react(chart2, chart2Data, chart2Layout);
448
});
449
}
450
451
// Zoom synchronization between charts
452
function synchronizeZoom(chart1, chart2) {
453
chart1.on('plotly_relayout', function(eventData) {
454
if (eventData['xaxis.range[0]'] !== undefined) {
455
Plotly.relayout(chart2, {
456
'xaxis.range': eventData['xaxis.range']
457
});
458
}
459
});
460
461
chart2.on('plotly_relayout', function(eventData) {
462
if (eventData['xaxis.range[0]'] !== undefined) {
463
Plotly.relayout(chart1, {
464
'xaxis.range': eventData['xaxis.range']
465
});
466
}
467
});
468
}
469
470
// Custom click behavior - drill down
471
myDiv.on('plotly_click', function(data) {
472
const point = data.points[0];
473
474
if (point.customdata && point.customdata.drillDown) {
475
// Load drill-down data
476
loadDrillDownData(point.customdata.category)
477
.then(newData => {
478
Plotly.react(myDiv, newData, newLayout);
479
});
480
}
481
});
482
483
// Responsive behavior on window resize
484
window.addEventListener('resize', function() {
485
Plotly.Plots.resize(myDiv);
486
});
487
488
// Custom selection behavior
489
myDiv.on('plotly_selected', function(data) {
490
if (data.points.length > 0) {
491
// Calculate statistics for selected points
492
const values = data.points.map(pt => pt.y);
493
const stats = {
494
count: values.length,
495
sum: values.reduce((a, b) => a + b, 0),
496
mean: values.reduce((a, b) => a + b, 0) / values.length,
497
min: Math.min(...values),
498
max: Math.max(...values)
499
};
500
501
// Update statistics display
502
updateStatsDisplay(stats);
503
}
504
});
505
```
506
507
## Event Data Reference
508
509
### Common Event Properties
510
511
```javascript { .api }
512
/**
513
* Common properties available in most event data objects
514
*/
515
interface BaseEventData {
516
event?: MouseEvent | TouchEvent;
517
points?: PlotlyPoint[];
518
range?: any;
519
lassoPoints?: any;
520
}
521
522
interface PlotlyPoint {
523
curveNumber: number;
524
pointNumber: number | number[];
525
pointIndex: number;
526
x: any;
527
y: any;
528
z?: any;
529
data: any;
530
fullData: any;
531
xaxis: any;
532
yaxis: any;
533
bbox?: {
534
x0: number;
535
x1: number;
536
y0: number;
537
y1: number;
538
};
539
distance?: number;
540
customdata?: any;
541
text?: string;
542
hovertext?: string;
543
}
544
```
545
546
### Event Timing and Performance
547
548
```javascript { .api }
549
/**
550
* Event timing considerations and performance options
551
*/
552
interface EventTiming {
553
// Debounce hover events for performance
554
hoverDebounce?: number;
555
556
// Throttle selection events
557
selectionThrottle?: number;
558
559
// Disable events for performance
560
staticPlot?: boolean;
561
}
562
```
563
564
**Usage Examples:**
565
566
```javascript
567
// Debounced hover handler for performance
568
let hoverTimeout;
569
myDiv.on('plotly_hover', function(data) {
570
clearTimeout(hoverTimeout);
571
hoverTimeout = setTimeout(() => {
572
// Process hover data
573
processHoverData(data);
574
}, 100);
575
});
576
577
// Throttled selection handler
578
let lastSelectionTime = 0;
579
myDiv.on('plotly_selected', function(data) {
580
const now = Date.now();
581
if (now - lastSelectionTime > 200) {
582
processSelection(data);
583
lastSelectionTime = now;
584
}
585
});
586
```