wavesurfer.js 4.6.0 → 5.2.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.
- package/CHANGES.md +41 -0
- package/README.md +6 -3
- package/dist/plugin/wavesurfer.cursor.js +9 -5
- package/dist/plugin/wavesurfer.cursor.js.map +1 -1
- package/dist/plugin/wavesurfer.cursor.min.js +2 -2
- package/dist/plugin/wavesurfer.cursor.min.js.map +1 -1
- package/dist/plugin/wavesurfer.elan.js +5 -4
- package/dist/plugin/wavesurfer.elan.js.map +1 -1
- package/dist/plugin/wavesurfer.elan.min.js +2 -2
- package/dist/plugin/wavesurfer.elan.min.js.map +1 -1
- package/dist/plugin/wavesurfer.markers.js +31 -12
- package/dist/plugin/wavesurfer.markers.js.map +1 -1
- package/dist/plugin/wavesurfer.markers.min.js +2 -2
- package/dist/plugin/wavesurfer.markers.min.js.map +1 -1
- package/dist/plugin/wavesurfer.mediasession.js +5 -4
- package/dist/plugin/wavesurfer.mediasession.js.map +1 -1
- package/dist/plugin/wavesurfer.mediasession.min.js +2 -2
- package/dist/plugin/wavesurfer.mediasession.min.js.map +1 -1
- package/dist/plugin/wavesurfer.microphone.js +5 -4
- package/dist/plugin/wavesurfer.microphone.js.map +1 -1
- package/dist/plugin/wavesurfer.microphone.min.js +2 -2
- package/dist/plugin/wavesurfer.microphone.min.js.map +1 -1
- package/dist/plugin/wavesurfer.minimap.js +5 -4
- package/dist/plugin/wavesurfer.minimap.js.map +1 -1
- package/dist/plugin/wavesurfer.minimap.min.js +2 -2
- package/dist/plugin/wavesurfer.minimap.min.js.map +1 -1
- package/dist/plugin/wavesurfer.playhead.js +324 -0
- package/dist/plugin/wavesurfer.playhead.js.map +1 -0
- package/dist/plugin/wavesurfer.playhead.min.js +7 -0
- package/dist/plugin/wavesurfer.playhead.min.js.map +1 -0
- package/dist/plugin/wavesurfer.regions.js +141 -86
- package/dist/plugin/wavesurfer.regions.js.map +1 -1
- package/dist/plugin/wavesurfer.regions.min.js +2 -2
- package/dist/plugin/wavesurfer.regions.min.js.map +1 -1
- package/dist/plugin/wavesurfer.spectrogram.js +70 -63
- package/dist/plugin/wavesurfer.spectrogram.js.map +1 -1
- package/dist/plugin/wavesurfer.spectrogram.min.js +2 -2
- package/dist/plugin/wavesurfer.spectrogram.min.js.map +1 -1
- package/dist/plugin/wavesurfer.timeline.js +32 -16
- package/dist/plugin/wavesurfer.timeline.js.map +1 -1
- package/dist/plugin/wavesurfer.timeline.min.js +2 -2
- package/dist/plugin/wavesurfer.timeline.min.js.map +1 -1
- package/dist/wavesurfer-html-init.js +5 -4
- package/dist/wavesurfer-html-init.js.map +1 -1
- package/dist/wavesurfer-html-init.min.js +2 -2
- package/dist/wavesurfer-html-init.min.js.map +1 -1
- package/dist/wavesurfer.js +326 -60
- package/dist/wavesurfer.js.map +1 -1
- package/dist/wavesurfer.min.js +2 -2
- package/dist/wavesurfer.min.js.map +1 -1
- package/package.json +19 -16
- package/src/drawer.canvasentry.js +16 -0
- package/src/drawer.js +30 -21
- package/src/drawer.multicanvas.js +63 -39
- package/src/plugin/cursor/index.js +3 -1
- package/src/plugin/markers/index.js +22 -8
- package/src/plugin/playhead/index.js +226 -0
- package/src/plugin/regions/index.js +28 -11
- package/src/plugin/regions/region.js +116 -75
- package/src/plugin/spectrogram/index.js +65 -61
- package/src/plugin/timeline/index.js +30 -19
- package/src/util/index.js +2 -0
- package/src/util/orientation.js +98 -0
- package/src/util/silence-mode.js +35 -0
- package/src/wavesurfer.js +41 -22
- package/src/webaudio.js +11 -2
|
@@ -15,6 +15,7 @@ export class Region {
|
|
|
15
15
|
this.util = ws.util;
|
|
16
16
|
this.style = this.util.style;
|
|
17
17
|
this.regionsUtil = regionsUtils;
|
|
18
|
+
this.vertical = ws.drawer.params.vertical;
|
|
18
19
|
|
|
19
20
|
this.id = params.id == null ? ws.util.getId() : params.id;
|
|
20
21
|
this.start = Number(params.start) || 0;
|
|
@@ -42,6 +43,7 @@ export class Region {
|
|
|
42
43
|
this.handleRightEl = null;
|
|
43
44
|
this.data = params.data || {};
|
|
44
45
|
this.attributes = params.attributes || {};
|
|
46
|
+
this.showTooltip = params.showTooltip ?? true;
|
|
45
47
|
|
|
46
48
|
this.maxLength = params.maxLength;
|
|
47
49
|
// It assumes the minLength parameter value, or the regionsMinLength parameter value, if the first one not provided
|
|
@@ -85,7 +87,7 @@ export class Region {
|
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
/* Update region params. */
|
|
88
|
-
update(params) {
|
|
90
|
+
update(params, eventParams) {
|
|
89
91
|
if (params.start != null) {
|
|
90
92
|
this.start = Number(params.start);
|
|
91
93
|
}
|
|
@@ -123,13 +125,13 @@ export class Region {
|
|
|
123
125
|
|
|
124
126
|
this.updateRender();
|
|
125
127
|
this.fireEvent('update');
|
|
126
|
-
this.wavesurfer.fireEvent('region-updated', this);
|
|
128
|
+
this.wavesurfer.fireEvent('region-updated', this, eventParams);
|
|
127
129
|
}
|
|
128
130
|
|
|
129
131
|
/* Remove a single region. */
|
|
130
132
|
remove() {
|
|
131
133
|
if (this.element) {
|
|
132
|
-
this.wrapper.removeChild(this.element);
|
|
134
|
+
this.wrapper.removeChild(this.element.domElement);
|
|
133
135
|
this.element = null;
|
|
134
136
|
this.fireEvent('remove');
|
|
135
137
|
this.wavesurfer.un('zoom', this._onRedraw);
|
|
@@ -168,20 +170,25 @@ export class Region {
|
|
|
168
170
|
|
|
169
171
|
/* Render a region as a DOM element. */
|
|
170
172
|
render() {
|
|
171
|
-
|
|
173
|
+
this.element = this.util.withOrientation(
|
|
174
|
+
this.wrapper.appendChild(document.createElement('region')),
|
|
175
|
+
this.vertical
|
|
176
|
+
);
|
|
172
177
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
this.element.className = 'wavesurfer-region';
|
|
179
|
+
if (this.showTooltip) {
|
|
180
|
+
this.element.title = this.formatTime(this.start, this.end);
|
|
181
|
+
}
|
|
182
|
+
this.element.setAttribute('data-id', this.id);
|
|
176
183
|
|
|
177
184
|
for (const attrname in this.attributes) {
|
|
178
|
-
|
|
185
|
+
this.element.setAttribute(
|
|
179
186
|
'data-region-' + attrname,
|
|
180
187
|
this.attributes[attrname]
|
|
181
188
|
);
|
|
182
189
|
}
|
|
183
190
|
|
|
184
|
-
this.style(
|
|
191
|
+
this.style(this.element, {
|
|
185
192
|
position: 'absolute',
|
|
186
193
|
zIndex: 2,
|
|
187
194
|
height: this.regionHeight,
|
|
@@ -190,11 +197,13 @@ export class Region {
|
|
|
190
197
|
|
|
191
198
|
/* Resize handles */
|
|
192
199
|
if (this.resize) {
|
|
193
|
-
this.handleLeftEl =
|
|
194
|
-
document.createElement('handle')
|
|
200
|
+
this.handleLeftEl = this.util.withOrientation(
|
|
201
|
+
this.element.appendChild(document.createElement('handle')),
|
|
202
|
+
this.vertical
|
|
195
203
|
);
|
|
196
|
-
this.handleRightEl =
|
|
197
|
-
document.createElement('handle')
|
|
204
|
+
this.handleRightEl = this.util.withOrientation(
|
|
205
|
+
this.element.appendChild(document.createElement('handle')),
|
|
206
|
+
this.vertical
|
|
198
207
|
);
|
|
199
208
|
|
|
200
209
|
this.handleLeftEl.className = 'wavesurfer-handle wavesurfer-handle-start';
|
|
@@ -202,7 +211,7 @@ export class Region {
|
|
|
202
211
|
|
|
203
212
|
// Default CSS properties for both handles.
|
|
204
213
|
const css = {
|
|
205
|
-
cursor: 'col-resize',
|
|
214
|
+
cursor: this.vertical ? 'row-resize' : 'col-resize',
|
|
206
215
|
position: 'absolute',
|
|
207
216
|
top: '0px',
|
|
208
217
|
width: '2px',
|
|
@@ -213,7 +222,11 @@ export class Region {
|
|
|
213
222
|
// Merge CSS properties per handle.
|
|
214
223
|
const handleLeftCss =
|
|
215
224
|
this.handleStyle.left !== 'none'
|
|
216
|
-
? Object.assign(
|
|
225
|
+
? Object.assign(
|
|
226
|
+
{ left: '0px' },
|
|
227
|
+
css,
|
|
228
|
+
this.handleStyle.left
|
|
229
|
+
)
|
|
217
230
|
: null;
|
|
218
231
|
const handleRightCss =
|
|
219
232
|
this.handleStyle.right !== 'none'
|
|
@@ -233,9 +246,8 @@ export class Region {
|
|
|
233
246
|
}
|
|
234
247
|
}
|
|
235
248
|
|
|
236
|
-
this.element = this.wrapper.appendChild(regionEl);
|
|
237
249
|
this.updateRender();
|
|
238
|
-
this.bindEvents(
|
|
250
|
+
this.bindEvents();
|
|
239
251
|
}
|
|
240
252
|
|
|
241
253
|
formatTime(start, end) {
|
|
@@ -301,7 +313,9 @@ export class Region {
|
|
|
301
313
|
);
|
|
302
314
|
}
|
|
303
315
|
|
|
304
|
-
|
|
316
|
+
if (this.showTooltip) {
|
|
317
|
+
this.element.title = this.formatTime(this.start, this.end);
|
|
318
|
+
}
|
|
305
319
|
}
|
|
306
320
|
}
|
|
307
321
|
|
|
@@ -407,20 +421,21 @@ export class Region {
|
|
|
407
421
|
let regionRightHalfTime;
|
|
408
422
|
|
|
409
423
|
// Scroll when the user is dragging within the threshold
|
|
410
|
-
const edgeScroll = (
|
|
424
|
+
const edgeScroll = (event) => {
|
|
425
|
+
let orientedEvent = this.util.withOrientation(event, this.vertical);
|
|
411
426
|
const duration = this.wavesurfer.getDuration();
|
|
412
427
|
if (!scrollDirection || (!drag && !resize)) {
|
|
413
428
|
return;
|
|
414
429
|
}
|
|
415
430
|
|
|
416
|
-
const x =
|
|
431
|
+
const x = orientedEvent.clientX;
|
|
417
432
|
let distanceBetweenCursorAndWrapperEdge = 0;
|
|
418
433
|
let regionHalfTimeWidth = 0;
|
|
419
434
|
let adjustment = 0;
|
|
420
435
|
|
|
421
436
|
// Get the currently selected time according to the mouse position
|
|
422
437
|
let time = this.regionsUtil.getRegionSnapToGridValue(
|
|
423
|
-
this.wavesurfer.drawer.handleEvent(
|
|
438
|
+
this.wavesurfer.drawer.handleEvent(event) * duration
|
|
424
439
|
);
|
|
425
440
|
|
|
426
441
|
if (drag) {
|
|
@@ -461,26 +476,28 @@ export class Region {
|
|
|
461
476
|
}
|
|
462
477
|
|
|
463
478
|
// Don't edgescroll if region has reached min or max limit
|
|
479
|
+
const wrapperScrollLeft = this.wrapper.scrollLeft;
|
|
480
|
+
|
|
464
481
|
if (scrollDirection === -1) {
|
|
465
|
-
if (Math.round(
|
|
482
|
+
if (Math.round(wrapperScrollLeft) === 0) {
|
|
466
483
|
return;
|
|
467
484
|
}
|
|
468
485
|
|
|
469
|
-
if (Math.round(
|
|
486
|
+
if (Math.round(wrapperScrollLeft - regionHalfTimeWidth + distanceBetweenCursorAndWrapperEdge) <= 0) {
|
|
470
487
|
return;
|
|
471
488
|
}
|
|
472
489
|
} else {
|
|
473
|
-
if (Math.round(
|
|
490
|
+
if (Math.round(wrapperScrollLeft) === maxScroll) {
|
|
474
491
|
return;
|
|
475
492
|
}
|
|
476
493
|
|
|
477
|
-
if (Math.round(
|
|
494
|
+
if (Math.round(wrapperScrollLeft + regionHalfTimeWidth - distanceBetweenCursorAndWrapperEdge) >= maxScroll) {
|
|
478
495
|
return;
|
|
479
496
|
}
|
|
480
497
|
}
|
|
481
498
|
|
|
482
499
|
// Update scroll position
|
|
483
|
-
let scrollLeft =
|
|
500
|
+
let scrollLeft = wrapperScrollLeft - adjustment + scrollSpeed * scrollDirection;
|
|
484
501
|
|
|
485
502
|
if (scrollDirection === -1) {
|
|
486
503
|
const calculatedLeft = Math.max(0 + regionHalfTimeWidth - distanceBetweenCursorAndWrapperEdge, scrollLeft);
|
|
@@ -498,26 +515,26 @@ export class Region {
|
|
|
498
515
|
|
|
499
516
|
// Repeat
|
|
500
517
|
window.requestAnimationFrame(() => {
|
|
501
|
-
edgeScroll(
|
|
518
|
+
edgeScroll(event);
|
|
502
519
|
});
|
|
503
520
|
};
|
|
504
521
|
|
|
505
|
-
const onDown = (
|
|
522
|
+
const onDown = (event) => {
|
|
506
523
|
const duration = this.wavesurfer.getDuration();
|
|
507
|
-
if (
|
|
524
|
+
if (event.touches && event.touches.length > 1) {
|
|
508
525
|
return;
|
|
509
526
|
}
|
|
510
|
-
touchId =
|
|
527
|
+
touchId = event.targetTouches ? event.targetTouches[0].identifier : null;
|
|
511
528
|
|
|
512
529
|
// stop the event propagation, if this region is resizable or draggable
|
|
513
530
|
// and the event is therefore handled here.
|
|
514
531
|
if (this.drag || this.resize) {
|
|
515
|
-
|
|
532
|
+
event.stopPropagation();
|
|
516
533
|
}
|
|
517
534
|
|
|
518
535
|
// Store the selected startTime we begun dragging or resizing
|
|
519
536
|
startTime = this.regionsUtil.getRegionSnapToGridValue(
|
|
520
|
-
this.wavesurfer.drawer.handleEvent(
|
|
537
|
+
this.wavesurfer.drawer.handleEvent(event, true) * duration
|
|
521
538
|
);
|
|
522
539
|
|
|
523
540
|
// Store the selected point of contact when we begin dragging
|
|
@@ -526,13 +543,17 @@ export class Region {
|
|
|
526
543
|
|
|
527
544
|
// Store for scroll calculations
|
|
528
545
|
maxScroll = this.wrapper.scrollWidth - this.wrapper.clientWidth;
|
|
529
|
-
|
|
546
|
+
|
|
547
|
+
wrapperRect = this.util.withOrientation(
|
|
548
|
+
this.wrapper.getBoundingClientRect(),
|
|
549
|
+
this.vertical
|
|
550
|
+
);
|
|
530
551
|
|
|
531
552
|
this.isResizing = false;
|
|
532
553
|
this.isDragging = false;
|
|
533
|
-
if (
|
|
554
|
+
if (event.target.tagName.toLowerCase() === 'handle') {
|
|
534
555
|
this.isResizing = true;
|
|
535
|
-
resize =
|
|
556
|
+
resize = event.target.classList.contains('wavesurfer-handle-start')
|
|
536
557
|
? 'start'
|
|
537
558
|
: 'end';
|
|
538
559
|
} else {
|
|
@@ -541,8 +562,8 @@ export class Region {
|
|
|
541
562
|
resize = false;
|
|
542
563
|
}
|
|
543
564
|
};
|
|
544
|
-
const onUp = (
|
|
545
|
-
if (
|
|
565
|
+
const onUp = (event) => {
|
|
566
|
+
if (event.touches && event.touches.length > 1) {
|
|
546
567
|
return;
|
|
547
568
|
}
|
|
548
569
|
|
|
@@ -557,17 +578,18 @@ export class Region {
|
|
|
557
578
|
if (updated) {
|
|
558
579
|
updated = false;
|
|
559
580
|
this.util.preventClick();
|
|
560
|
-
this.fireEvent('update-end',
|
|
561
|
-
this.wavesurfer.fireEvent('region-update-end', this,
|
|
581
|
+
this.fireEvent('update-end', event);
|
|
582
|
+
this.wavesurfer.fireEvent('region-update-end', this, event);
|
|
562
583
|
}
|
|
563
584
|
};
|
|
564
|
-
const onMove = (
|
|
585
|
+
const onMove = (event) => {
|
|
565
586
|
const duration = this.wavesurfer.getDuration();
|
|
587
|
+
let orientedEvent = this.util.withOrientation(event, this.vertical);
|
|
566
588
|
|
|
567
|
-
if (
|
|
589
|
+
if (event.touches && event.touches.length > 1) {
|
|
568
590
|
return;
|
|
569
591
|
}
|
|
570
|
-
if (
|
|
592
|
+
if (event.targetTouches && event.targetTouches[0].identifier != touchId) {
|
|
571
593
|
return;
|
|
572
594
|
}
|
|
573
595
|
if (!drag && !resize) {
|
|
@@ -576,7 +598,7 @@ export class Region {
|
|
|
576
598
|
|
|
577
599
|
const oldTime = startTime;
|
|
578
600
|
let time = this.regionsUtil.getRegionSnapToGridValue(
|
|
579
|
-
this.wavesurfer.drawer.handleEvent(
|
|
601
|
+
this.wavesurfer.drawer.handleEvent(event) * duration
|
|
580
602
|
);
|
|
581
603
|
|
|
582
604
|
if (drag) {
|
|
@@ -634,36 +656,22 @@ export class Region {
|
|
|
634
656
|
}
|
|
635
657
|
|
|
636
658
|
if (
|
|
637
|
-
this.scroll &&
|
|
638
|
-
container.clientWidth < this.wrapper.scrollWidth
|
|
659
|
+
this.scroll && container.clientWidth < this.wrapper.scrollWidth
|
|
639
660
|
) {
|
|
640
661
|
// Triggering edgescroll from within edgeScrollWidth
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
scrollDirection = 1;
|
|
649
|
-
} else {
|
|
650
|
-
scrollDirection = null;
|
|
651
|
-
}
|
|
662
|
+
let x = orientedEvent.clientX;
|
|
663
|
+
|
|
664
|
+
// Check direction
|
|
665
|
+
if (x < wrapperRect.left + this.edgeScrollWidth) {
|
|
666
|
+
scrollDirection = -1;
|
|
667
|
+
} else if (x > wrapperRect.right - this.edgeScrollWidth) {
|
|
668
|
+
scrollDirection = 1;
|
|
652
669
|
} else {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
// Check direction
|
|
656
|
-
if (x < wrapperRect.left + this.edgeScrollWidth) {
|
|
657
|
-
scrollDirection = -1;
|
|
658
|
-
} else if (x > wrapperRect.right - this.edgeScrollWidth) {
|
|
659
|
-
scrollDirection = 1;
|
|
660
|
-
} else {
|
|
661
|
-
scrollDirection = null;
|
|
662
|
-
}
|
|
670
|
+
scrollDirection = null;
|
|
663
671
|
}
|
|
664
672
|
|
|
665
673
|
if (scrollDirection) {
|
|
666
|
-
edgeScroll(
|
|
674
|
+
edgeScroll(event);
|
|
667
675
|
}
|
|
668
676
|
}
|
|
669
677
|
};
|
|
@@ -672,20 +680,20 @@ export class Region {
|
|
|
672
680
|
this.element.addEventListener('touchstart', onDown);
|
|
673
681
|
|
|
674
682
|
document.body.addEventListener('mousemove', onMove);
|
|
675
|
-
document.body.addEventListener('touchmove', onMove);
|
|
683
|
+
document.body.addEventListener('touchmove', onMove, {passive: false});
|
|
676
684
|
|
|
677
|
-
document.
|
|
685
|
+
document.addEventListener('mouseup', onUp);
|
|
678
686
|
document.body.addEventListener('touchend', onUp);
|
|
679
687
|
|
|
680
688
|
this.on('remove', () => {
|
|
681
|
-
document.
|
|
689
|
+
document.removeEventListener('mouseup', onUp);
|
|
682
690
|
document.body.removeEventListener('touchend', onUp);
|
|
683
691
|
document.body.removeEventListener('mousemove', onMove);
|
|
684
692
|
document.body.removeEventListener('touchmove', onMove);
|
|
685
693
|
});
|
|
686
694
|
|
|
687
695
|
this.wavesurfer.on('destroy', () => {
|
|
688
|
-
document.
|
|
696
|
+
document.removeEventListener('mouseup', onUp);
|
|
689
697
|
document.body.removeEventListener('touchend', onUp);
|
|
690
698
|
});
|
|
691
699
|
}
|
|
@@ -700,10 +708,33 @@ export class Region {
|
|
|
700
708
|
delta = this.start * -1;
|
|
701
709
|
}
|
|
702
710
|
|
|
711
|
+
const eventParams = {
|
|
712
|
+
direction: this._getDragDirection(delta),
|
|
713
|
+
action: 'drag'
|
|
714
|
+
};
|
|
715
|
+
|
|
703
716
|
this.update({
|
|
704
717
|
start: this.start + delta,
|
|
705
718
|
end: this.end + delta
|
|
706
|
-
});
|
|
719
|
+
}, eventParams);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Returns the direction of dragging region based on delta
|
|
724
|
+
* Negative delta means region is moving to the left
|
|
725
|
+
* Positive - to the right
|
|
726
|
+
* For zero delta the direction is not defined
|
|
727
|
+
* @param {number} delta Drag offset
|
|
728
|
+
* @returns {string|null} Direction 'left', 'right' or null
|
|
729
|
+
*/
|
|
730
|
+
_getDragDirection(delta) {
|
|
731
|
+
if (delta < 0) {
|
|
732
|
+
return 'left';
|
|
733
|
+
}
|
|
734
|
+
if (delta > 0) {
|
|
735
|
+
return 'right';
|
|
736
|
+
}
|
|
737
|
+
return null;
|
|
707
738
|
}
|
|
708
739
|
|
|
709
740
|
/**
|
|
@@ -716,6 +747,11 @@ export class Region {
|
|
|
716
747
|
*/
|
|
717
748
|
onResize(delta, direction) {
|
|
718
749
|
const duration = this.wavesurfer.getDuration();
|
|
750
|
+
const eventParams = {
|
|
751
|
+
action: 'resize',
|
|
752
|
+
direction: direction === 'start' ? 'right' : 'left'
|
|
753
|
+
};
|
|
754
|
+
|
|
719
755
|
if (direction === 'start') {
|
|
720
756
|
// Check if changing the start by the given delta would result in the region being smaller than minLength
|
|
721
757
|
// Ignore cases where we are making the region wider rather than shrinking it
|
|
@@ -730,7 +766,7 @@ export class Region {
|
|
|
730
766
|
this.update({
|
|
731
767
|
start: Math.min(this.start + delta, this.end),
|
|
732
768
|
end: Math.max(this.start + delta, this.end)
|
|
733
|
-
});
|
|
769
|
+
}, eventParams);
|
|
734
770
|
} else {
|
|
735
771
|
// Check if changing the end by the given delta would result in the region being smaller than minLength
|
|
736
772
|
// Ignore cases where we are making the region wider rather than shrinking it
|
|
@@ -745,12 +781,17 @@ export class Region {
|
|
|
745
781
|
this.update({
|
|
746
782
|
start: Math.min(this.end + delta, this.start),
|
|
747
783
|
end: Math.max(this.end + delta, this.start)
|
|
748
|
-
});
|
|
784
|
+
}, eventParams);
|
|
749
785
|
}
|
|
750
786
|
}
|
|
751
787
|
|
|
752
788
|
updateHandlesResize(resize) {
|
|
753
|
-
|
|
789
|
+
let cursorStyle;
|
|
790
|
+
if (resize) {
|
|
791
|
+
cursorStyle = this.vertical ? 'row-resize' : 'col-resize';
|
|
792
|
+
} else {
|
|
793
|
+
cursorStyle = 'auto';
|
|
794
|
+
}
|
|
754
795
|
|
|
755
796
|
this.handleLeftEl && this.style(this.handleLeftEl, { cursor: cursorStyle });
|
|
756
797
|
this.handleRightEl && this.style(this.handleRightEl, { cursor: cursorStyle });
|
|
@@ -254,30 +254,32 @@ export default class SpectrogramPlugin {
|
|
|
254
254
|
const width = my.width;
|
|
255
255
|
const pixels = my.resample(frequenciesData);
|
|
256
256
|
const heightFactor = my.buffer ? 2 / my.buffer.numberOfChannels : 1;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
for (
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
257
|
+
if (spectrCc) {
|
|
258
|
+
const imageData = spectrCc.createImageData(width, height);
|
|
259
|
+
let i;
|
|
260
|
+
let j;
|
|
261
|
+
let k;
|
|
262
|
+
|
|
263
|
+
for (i = 0; i < pixels.length; i++) {
|
|
264
|
+
for (j = 0; j < pixels[i].length; j++) {
|
|
265
|
+
const colorMap = my.colorMap[pixels[i][j]];
|
|
266
|
+
/* eslint-disable max-depth */
|
|
267
|
+
for (k = 0; k < heightFactor; k++) {
|
|
268
|
+
let y = height - j * heightFactor;
|
|
269
|
+
if (heightFactor === 2 && k === 1) {
|
|
270
|
+
y--;
|
|
271
|
+
}
|
|
272
|
+
const redIndex = y * (width * 4) + i * 4;
|
|
273
|
+
imageData.data[redIndex] = colorMap[0] * 255;
|
|
274
|
+
imageData.data[redIndex + 1] = colorMap[1] * 255;
|
|
275
|
+
imageData.data[redIndex + 2] = colorMap[2] * 255;
|
|
276
|
+
imageData.data[redIndex + 3] = colorMap[3] * 255;
|
|
270
277
|
}
|
|
271
|
-
|
|
272
|
-
imageData.data[redIndex] = colorMap[0] * 255;
|
|
273
|
-
imageData.data[redIndex + 1] = colorMap[1] * 255;
|
|
274
|
-
imageData.data[redIndex + 2] = colorMap[2] * 255;
|
|
275
|
-
imageData.data[redIndex + 3] = colorMap[3] * 255;
|
|
278
|
+
/* eslint-enable max-depth */
|
|
276
279
|
}
|
|
277
|
-
/* eslint-enable max-depth */
|
|
278
280
|
}
|
|
281
|
+
spectrCc.putImageData(imageData, 0, 0);
|
|
279
282
|
}
|
|
280
|
-
spectrCc.putImageData(imageData, 0, 0);
|
|
281
283
|
}
|
|
282
284
|
|
|
283
285
|
getFrequencies(callback) {
|
|
@@ -378,47 +380,49 @@ export default class SpectrogramPlugin {
|
|
|
378
380
|
this.labelsEl.height = this.height;
|
|
379
381
|
this.labelsEl.width = bgWidth;
|
|
380
382
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
383
|
+
if (ctx) {
|
|
384
|
+
// fill background
|
|
385
|
+
ctx.fillStyle = bgFill;
|
|
386
|
+
ctx.fillRect(0, 0, bgWidth, getMaxY);
|
|
387
|
+
ctx.fill();
|
|
388
|
+
let i;
|
|
389
|
+
|
|
390
|
+
// render labels
|
|
391
|
+
for (i = 0; i <= labelIndex; i++) {
|
|
392
|
+
ctx.textAlign = textAlign;
|
|
393
|
+
ctx.textBaseline = 'middle';
|
|
394
|
+
|
|
395
|
+
const freq = freqStart + step * i;
|
|
396
|
+
const index = Math.round(
|
|
397
|
+
(freq / (this.sampleRate / 2)) * this.fftSamples
|
|
398
|
+
);
|
|
399
|
+
const label = this.freqType(freq);
|
|
400
|
+
const units = this.unitType(freq);
|
|
401
|
+
const yLabelOffset = 2;
|
|
402
|
+
const x = 16;
|
|
403
|
+
let y;
|
|
404
|
+
|
|
405
|
+
if (i == 0) {
|
|
406
|
+
y = getMaxY + i - 10;
|
|
407
|
+
// unit label
|
|
408
|
+
ctx.fillStyle = textColorUnit;
|
|
409
|
+
ctx.font = fontSizeUnit + ' ' + fontType;
|
|
410
|
+
ctx.fillText(units, x + 24, y);
|
|
411
|
+
// freq label
|
|
412
|
+
ctx.fillStyle = textColorFreq;
|
|
413
|
+
ctx.font = fontSizeFreq + ' ' + fontType;
|
|
414
|
+
ctx.fillText(label, x, y);
|
|
415
|
+
} else {
|
|
416
|
+
y = getMaxY - i * 50 + yLabelOffset;
|
|
417
|
+
// unit label
|
|
418
|
+
ctx.fillStyle = textColorUnit;
|
|
419
|
+
ctx.font = fontSizeUnit + ' ' + fontType;
|
|
420
|
+
ctx.fillText(units, x + 24, y);
|
|
421
|
+
// freq label
|
|
422
|
+
ctx.fillStyle = textColorFreq;
|
|
423
|
+
ctx.font = fontSizeFreq + ' ' + fontType;
|
|
424
|
+
ctx.fillText(label, x, y);
|
|
425
|
+
}
|
|
422
426
|
}
|
|
423
427
|
}
|
|
424
428
|
}
|
|
@@ -434,7 +434,10 @@ export default class TimelinePlugin {
|
|
|
434
434
|
*/
|
|
435
435
|
setFillStyles(fillStyle) {
|
|
436
436
|
this.canvases.forEach(canvas => {
|
|
437
|
-
canvas.getContext('2d')
|
|
437
|
+
const context = canvas.getContext('2d');
|
|
438
|
+
if (context) {
|
|
439
|
+
context.fillStyle = fillStyle;
|
|
440
|
+
}
|
|
438
441
|
});
|
|
439
442
|
}
|
|
440
443
|
|
|
@@ -445,7 +448,10 @@ export default class TimelinePlugin {
|
|
|
445
448
|
*/
|
|
446
449
|
setFonts(font) {
|
|
447
450
|
this.canvases.forEach(canvas => {
|
|
448
|
-
canvas.getContext('2d')
|
|
451
|
+
const context = canvas.getContext('2d');
|
|
452
|
+
if (context) {
|
|
453
|
+
context.font = font;
|
|
454
|
+
}
|
|
449
455
|
});
|
|
450
456
|
}
|
|
451
457
|
|
|
@@ -471,14 +477,17 @@ export default class TimelinePlugin {
|
|
|
471
477
|
};
|
|
472
478
|
|
|
473
479
|
if (intersection.x1 < intersection.x2) {
|
|
474
|
-
canvas
|
|
475
|
-
.getContext('2d')
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
480
|
+
const context = canvas
|
|
481
|
+
.getContext('2d');
|
|
482
|
+
if (context) {
|
|
483
|
+
context
|
|
484
|
+
.fillRect(
|
|
485
|
+
intersection.x1 - leftOffset,
|
|
486
|
+
intersection.y1,
|
|
487
|
+
intersection.x2 - intersection.x1,
|
|
488
|
+
intersection.y2 - intersection.y1
|
|
489
|
+
);
|
|
490
|
+
}
|
|
482
491
|
}
|
|
483
492
|
});
|
|
484
493
|
}
|
|
@@ -496,18 +505,20 @@ export default class TimelinePlugin {
|
|
|
496
505
|
|
|
497
506
|
this.canvases.forEach(canvas => {
|
|
498
507
|
const context = canvas.getContext('2d');
|
|
499
|
-
|
|
508
|
+
if (context) {
|
|
509
|
+
const canvasWidth = context.canvas.width;
|
|
500
510
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
511
|
+
if (xOffset > x + textWidth) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
504
514
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
515
|
+
if (xOffset + canvasWidth > x && context) {
|
|
516
|
+
textWidth = context.measureText(text).width;
|
|
517
|
+
context.fillText(text, x - xOffset, y);
|
|
518
|
+
}
|
|
509
519
|
|
|
510
|
-
|
|
520
|
+
xOffset += canvasWidth;
|
|
521
|
+
}
|
|
511
522
|
});
|
|
512
523
|
}
|
|
513
524
|
|
package/src/util/index.js
CHANGED
|
@@ -10,3 +10,5 @@ export { default as debounce } from 'debounce';
|
|
|
10
10
|
export { default as preventClick } from './prevent-click';
|
|
11
11
|
export { default as fetchFile } from './fetch';
|
|
12
12
|
export { default as clamp } from './clamp';
|
|
13
|
+
export { default as withOrientation } from './orientation';
|
|
14
|
+
export { default as ignoreSilenceMode } from './silence-mode';
|