@checksub_team/peaks_timeline 1.4.34 → 1.4.37

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,987 +1,987 @@
1
- /**
2
- * @file
3
- *
4
- * Defines the {@link SourceGroup} class.
5
- *
6
- * @module source-group
7
- */
8
-
9
- define([
10
- './waveform-builder',
11
- './waveform-shape',
12
- './utils',
13
- 'konva'
14
- ], function(
15
- WaveformBuilder,
16
- WaveformShape,
17
- Utils,
18
- Konva) {
19
- 'use strict';
20
-
21
- var SPACING_BETWEEN_PREVIEW_AND_BORDER_RATIO = 0.15;
22
- var SPACING_BETWEEN_PREVIEWS = 1.5;
23
- var HANDLE_WIDTH = 8;
24
- var CORNER_RADIUS = 8;
25
- var SELECTED_BORDER_WIDTH = 6;
26
-
27
- /**
28
- * Creates a source group for the given source.
29
- *
30
- * @class
31
- * @alias SourceGroup
32
- *
33
- * @param {Source} source
34
- * @param {Peaks} peaks
35
- * @param {SourcesLayer} layer
36
- * @param {WaveformOverview|WaveformZoomView} view
37
- */
38
-
39
- function SourceGroup(source, peaks, layer, view) {
40
- this._source = source;
41
- this._peaks = peaks;
42
- this._layer = layer;
43
- this._view = view;
44
-
45
- var self = this;
46
-
47
- this._x = this._view.timeToPixels(source.startTime);
48
- this._width = this._view.timeToPixels(source.endTime - source.startTime);
49
- this._unwrappedHeight = source.binaryHeight && source.previewHeight ?
50
- source.binaryHeight + source.previewHeight :
51
- this._peaks.options.lineHeight;
52
- this._wrappedHeight = this._peaks.options.wrappedLineHeight;
53
-
54
- this._previewList = [];
55
-
56
- this._group = new Konva.Group({
57
- x: this._x,
58
- draggable: this._source.draggable,
59
- dragBoundFunc: function() {
60
- return {
61
- x: this.absolutePosition().x,
62
- y: this.absolutePosition().y
63
- };
64
- },
65
- clipFunc: function(ctx) {
66
- self.drawSourceShape(ctx);
67
- }
68
- });
69
-
70
- this._group.on('dragstart', this._onSourceGroupDragStart.bind(this));
71
- this._group.on('mouseover', function() {
72
- self._view.setHoveredElement(self);
73
- if (self._view.getCurrentMode() === 'cut') {
74
- self.toggleDragging(false);
75
- self.toggleResizing(false);
76
- }
77
- });
78
- this._group.on('mouseout', function() {
79
- self._view.setHoveredElement(null);
80
- if (self._view.getCurrentMode() === 'cut') {
81
- self.toggleDragging(true);
82
- self.toggleResizing(true);
83
- }
84
- });
85
- this._group.on('dragend', this._onSourceGroupDragEnd.bind(this));
86
-
87
- this._addWrap(true);
88
- this._addUnwrap(true);
89
- this._addHandles(true);
90
-
91
- this.setWrapping(source.wrapped);
92
- }
93
-
94
- // SourceGroup.prototype.rescale = function() {
95
- // this.update();
96
-
97
- // this._previewList.forEach(function(preview) {
98
- // if (preview.loaded) {
99
- // switch (preview.type) {
100
- // case 'audio':
101
- // preview.group.getChildren()[0].rescale(true);
102
- // break;
103
- // case 'video':
104
- // case 'image':
105
- // default:
106
- // // No resampling
107
- // }
108
- // }
109
- // });
110
- // };
111
-
112
- SourceGroup.prototype._onSourceGroupDragStart = function() {
113
- this._dragged = true;
114
- this._mouseDownX = this._view.getPointerPosition().x;
115
- this._initialStartTime = this._source.startTime;
116
- this._initialStartPixel = this._view.timeToPixels(this._initialStartTime);
117
- this._initialEndTime = this._source.endTime;
118
- this._initialEndPixel = this._view.timeToPixels(this._initialEndTime);
119
- this._initialFrameOffset = this._view.getFrameOffset();
120
- };
121
-
122
- SourceGroup.prototype._onSourceGroupDragEnd = function() {
123
- this._dragged = false;
124
- this._view.updateTimelineLength();
125
- this._peaks.emit('sources.updated');
126
- };
127
-
128
- SourceGroup.prototype._onSourceGroupDrag = function(draggedElement) {
129
- var self = this;
130
-
131
- var pos = this._view.updateWithAutoScroll(
132
- draggedElement,
133
- function() {
134
- var mousePos = Math.min(
135
- self._view.getWidth() - self._peaks.options.autoScrollThreshold * self._view.getWidth(),
136
- Math.max(
137
- 0,
138
- self._view.getPointerPosition().x
139
- )
140
- );
141
-
142
- var diff = mousePos - self._mouseDownX;
143
-
144
- self._layer.updateSource(
145
- self._source,
146
- self._initialStartPixel + diff + (self._view.getFrameOffset() - self._initialFrameOffset),
147
- self._initialEndPixel + diff + (self._view.getFrameOffset() - self._initialFrameOffset),
148
- self._view.getPointerPosition().y
149
- );
150
-
151
- self._view.setTimelineLength(
152
- self._view.timeToPixels(self._source.endTime) + self._view.getWidth()
153
- );
154
- }
155
- );
156
-
157
- return {
158
- x: pos.x,
159
- y: pos.y
160
- };
161
- };
162
-
163
- SourceGroup.prototype._onSourceGroupHandleDrag = function(draggedElement, dragPos, leftHandle) {
164
- var self = this;
165
-
166
- var pos = this._view.updateWithAutoScroll(
167
- draggedElement,
168
- function() {
169
- self._layer.updateSource(
170
- self._source,
171
- leftHandle ? dragPos.x + self._view.getFrameOffset() : null,
172
- leftHandle ? null : dragPos.x + draggedElement.width() + self._view.getFrameOffset()
173
- );
174
- }
175
- );
176
-
177
- this._view.setTimelineLength(
178
- this._view.timeToPixels(this._source.endTime) + this._view.getWidth()
179
- );
180
-
181
- return {
182
- x: pos.x,
183
- y: pos.y
184
- };
185
- };
186
-
187
- SourceGroup.prototype.update = function() {
188
- var startPixel = this._view.timeToPixels(this._source.startTime);
189
- var endPixel = this._view.timeToPixels(this._source.endTime);
190
- var frameOffset = this._view.timeToPixels(this._view.getTimeOffset());
191
-
192
- this._group.x(startPixel - frameOffset);
193
-
194
- this._x = startPixel;
195
-
196
- var newWidth = endPixel - startPixel;
197
-
198
- if (newWidth !== this._width) {
199
- this._width = newWidth;
200
-
201
- // update handles
202
- this._rightHandle.x(newWidth - HANDLE_WIDTH);
203
-
204
- // update unwrap
205
- this.updatePreviews();
206
-
207
- // update wrap
208
- var title = this._wrap.getChildren(function(node) {
209
- return node.getClassName() === 'Text';
210
- });
211
-
212
- if (title) {
213
- title.width(newWidth - 10);
214
- }
215
- }
216
- };
217
-
218
- SourceGroup.prototype.setWrapping = function(wrap) {
219
- if (wrap) {
220
- this.wrap();
221
- this._height = this._wrappedHeight;
222
- }
223
- else {
224
- this.unwrap();
225
- this._height = this._unwrappedHeight;
226
- }
227
-
228
- this.setHandlesWrapping(wrap);
229
- };
230
-
231
- SourceGroup.prototype.setHandlesWrapping = function(wrap) {
232
- if (wrap) {
233
- this._leftHandle.height(this._wrappedHeight);
234
- this._rightHandle.height(this._wrappedHeight);
235
- }
236
- else {
237
- this._leftHandle.height(this._unwrappedHeight);
238
- this._rightHandle.height(this._unwrappedHeight);
239
- }
240
- };
241
-
242
- SourceGroup.prototype._addHandles = function(forceCreate) {
243
- var self = this;
244
-
245
- if (!this._leftHandle || forceCreate) {
246
- this._leftHandle = new Konva.Rect({
247
- x: 0,
248
- width: HANDLE_WIDTH,
249
- height: this._unwrappedHeight,
250
- visible: true,
251
- draggable: this._source.resizable,
252
- dragBoundFunc: function(pos) {
253
- return self._onSourceGroupHandleDrag(this, pos, true);
254
- }
255
- });
256
-
257
- if (this._source.resizable) {
258
- this._leftHandle.on('dragend', function() {
259
- if (this._scrollingInterval) {
260
- clearInterval(this._scrollingInterval);
261
- this._scrollingInterval = null;
262
- }
263
- });
264
-
265
- this._leftHandle.on('mouseover', function() {
266
- self._view.setCursor('ew-resize');
267
- });
268
-
269
- this._leftHandle.on('mouseout', function() {
270
- self._view.setCursor('default');
271
- });
272
- }
273
- }
274
-
275
- if (!this._rightHandle || forceCreate) {
276
- this._rightHandle = new Konva.Rect({
277
- x: this._width - HANDLE_WIDTH,
278
- width: HANDLE_WIDTH,
279
- height: this._unwrappedHeight,
280
- visible: true,
281
- draggable: this._source.resizable,
282
- dragBoundFunc: function(pos) {
283
- return self._onSourceGroupHandleDrag(this, pos, false);
284
- }
285
- });
286
-
287
- if (this._source.resizable) {
288
- this._rightHandle.on('dragend', function() {
289
- if (this._scrollingInterval) {
290
- clearInterval(this._scrollingInterval);
291
- this._scrollingInterval = null;
292
- }
293
- });
294
-
295
- this._rightHandle.on('mouseover', function() {
296
- self._view.setCursor('ew-resize');
297
- });
298
-
299
- this._rightHandle.on('mouseout', function() {
300
- self._view.setCursor('default');
301
- });
302
- }
303
- }
304
-
305
- this._group.add(this._leftHandle);
306
- this._group.add(this._rightHandle);
307
- };
308
-
309
- SourceGroup.prototype._addUnwrap = function(forceCreate) {
310
- if (!this._unwrap || forceCreate) {
311
- this._unwrap = this._createUnwrap();
312
- this._unwrap.visible(false);
313
- }
314
-
315
- this._group.add(this._unwrap);
316
- };
317
-
318
- SourceGroup.prototype.toggleDragging = function(bool) {
319
- var background;
320
-
321
- if (this._wrap) {
322
- background = this._wrap.getChildren(function(node) {
323
- return node.getClassName() === 'Shape';
324
- });
325
-
326
- if (background) {
327
- background.draggable(bool);
328
- }
329
- }
330
- if (this._unwrap) {
331
- background = this._unwrap.getChildren(function(node) {
332
- return node.getClassName() === 'Shape';
333
- });
334
-
335
- if (background) {
336
- background.draggable(bool);
337
- }
338
- }
339
- };
340
-
341
- SourceGroup.prototype.toggleResizing = function(bool) {
342
- if (this._leftHandle) {
343
- this._leftHandle.draggable(bool);
344
- }
345
- if (this._rightHandle) {
346
- this._rightHandle.draggable(bool);
347
- }
348
- };
349
-
350
- SourceGroup.prototype.drawSourceShape = function(ctx, shape) {
351
- var radius = Math.max(
352
- 1,
353
- Math.min(
354
- this._width / 2,
355
- Math.min(
356
- CORNER_RADIUS,
357
- this._height / 2
358
- )
359
- )
360
- );
361
- var x = Math.max(
362
- 0,
363
- this._view.getFrameOffset() - this._x - radius
364
- );
365
- var width = Math.min(
366
- this._width - x,
367
- this._view.getOriginalWidth() + radius - Math.max(
368
- 0,
369
- this._x - this._view.getFrameOffset()
370
- )
371
- );
372
- var xWidth = x + width;
373
-
374
- ctx.beginPath();
375
- ctx.moveTo(x + radius, 0);
376
- ctx.lineTo(xWidth - radius, 0);
377
- ctx.quadraticCurveTo(xWidth, 0, xWidth, radius);
378
- ctx.lineTo(xWidth, this._height - radius);
379
- ctx.quadraticCurveTo(xWidth, this._height, xWidth - radius, this._height);
380
- ctx.lineTo(x + radius, this._height);
381
- ctx.quadraticCurveTo(x, this._height, x, this._height - radius);
382
- ctx.lineTo(x, radius);
383
- ctx.quadraticCurveTo(x, 0, x + radius, 0);
384
- ctx.closePath();
385
-
386
- if (shape) {
387
- ctx.fillStrokeShape(shape);
388
- }
389
- };
390
-
391
- SourceGroup.prototype._createUnwrap = function() {
392
- var unwrap = new Konva.Group({
393
- width: this._width,
394
- height: this._unwrappedHeight,
395
- draggable: this._source.draggable,
396
- dragBoundFunc: function() {
397
- return {
398
- x: this.absolutePosition().x,
399
- y: this.absolutePosition().y
400
- };
401
- }
402
- });
403
-
404
- var self = this;
405
-
406
- var background = new Konva.Shape({
407
- fill: this._source.color,
408
- stroke: this._source.borderColor,
409
- strokeWidth: this._source.borderWidth,
410
- sceneFunc: function(ctx, shape) {
411
- self.drawSourceShape(ctx, shape);
412
- },
413
- draggable: this._source.draggable,
414
- dragBoundFunc: function() {
415
- return self._onSourceGroupDrag(this);
416
- }
417
- });
418
-
419
- if (this._source.draggable) {
420
- background.on('mouseenter', function() {
421
- self._view.setCursor('pointer');
422
- });
423
- background.on('mouseout', function() {
424
- self._view.setCursor('default');
425
- });
426
-
427
- background.on('dragstart', function() {
428
- this._scrollInterval = null;
429
- });
430
-
431
- background.on('dragend', function() {
432
- if (this._scrollingInterval) {
433
- clearInterval(this._scrollingInterval);
434
- this._scrollingInterval = null;
435
- }
436
- });
437
- }
438
-
439
- unwrap.add(background);
440
-
441
- return unwrap;
442
- };
443
-
444
- SourceGroup.prototype._addWrap = function(forceCreate) {
445
- if (!this._wrap || forceCreate) {
446
- this._wrap = this._createWrap();
447
- this._wrap.visible(false);
448
- }
449
-
450
- this._group.add(this._wrap);
451
- };
452
-
453
- SourceGroup.prototype._createWrap = function() {
454
- var wrap = new Konva.Group({
455
- width: this._width,
456
- height: this._wrappedHeight,
457
- draggable: this._source.draggable,
458
- dragBoundFunc: function() {
459
- return {
460
- x: this.absolutePosition().x,
461
- y: this.absolutePosition().y
462
- };
463
- }
464
- });
465
-
466
- var self = this;
467
-
468
- var background = new Konva.Shape({
469
- fill: this._source.color,
470
- stroke: this._source.borderColor,
471
- strokeWidth: this._source.borderWidth,
472
- sceneFunc: function(ctx, shape) {
473
- self.drawSourceShape(ctx, shape);
474
- },
475
- draggable: this._source.draggable,
476
- dragBoundFunc: function() {
477
- return self._onSourceGroupDrag(this);
478
- }
479
- });
480
-
481
- if (this._source.draggable) {
482
- background.on('mouseenter', function() {
483
- self._view.setCursor('pointer');
484
- });
485
- background.on('mouseout', function() {
486
- self._view.setCursor('default');
487
- });
488
-
489
- background.on('dragstart', function() {
490
- this._scrollInterval = null;
491
- });
492
-
493
- background.on('dragend', function() {
494
- if (this._scrollingInterval) {
495
- clearInterval(this._scrollingInterval);
496
- this._scrollingInterval = null;
497
- }
498
- });
499
- }
500
-
501
- var title = new Konva.Text({
502
- x: 5,
503
- width: this._width - 10,
504
- height: this._wrappedHeight,
505
- text: Utils.removeLineBreaks(this._source.title),
506
- textAlign: 'left',
507
- verticalAlign: 'middle',
508
- fontSize: 14,
509
- fontFamily: 'Open Sans',
510
- fill: this._source.textColor,
511
- wrap: 'none',
512
- ellipsis: true,
513
- listening: false
514
- });
515
-
516
- wrap.add(background);
517
- wrap.add(title);
518
-
519
- return wrap;
520
- };
521
-
522
- SourceGroup.prototype.getWidth = function() {
523
- return this._width;
524
- };
525
-
526
- SourceGroup.prototype.getX = function() {
527
- return this._x;
528
- };
529
-
530
- SourceGroup.prototype.getY = function() {
531
- return this._group.absolutePosition().y;
532
- };
533
-
534
- SourceGroup.prototype.x = function(value) {
535
- if (value) {
536
- return this._group.x(value);
537
- }
538
- else {
539
- return this._group.x();
540
- }
541
- };
542
-
543
- SourceGroup.prototype.y = function(value) {
544
- if (value) {
545
- return this._group.y(value);
546
- }
547
- else {
548
- return this._group.y();
549
- }
550
- };
551
-
552
- SourceGroup.prototype.getSource = function() {
553
- return this._source;
554
- };
555
-
556
- SourceGroup.prototype.startDrag = function() {
557
- return this._group.startDrag();
558
- };
559
-
560
- SourceGroup.prototype.stopDrag = function() {
561
- return this._group.stopDrag();
562
- };
563
-
564
- SourceGroup.prototype.addToGroup = function(group) {
565
- group.add(this._group);
566
- };
567
-
568
- SourceGroup.prototype.isDescendantOf = function(group) {
569
- group.isAncestorOf(this._group);
570
- };
571
-
572
- SourceGroup.prototype.moveTo = function(group) {
573
- this._group.moveTo(group);
574
- };
575
-
576
- SourceGroup.prototype.getParent = function() {
577
- return this._group.getParent();
578
- };
579
-
580
- SourceGroup.prototype.remove = function() {
581
- this._group.remove();
582
- };
583
-
584
- SourceGroup.prototype.add = function(element) {
585
- this._group.add(element);
586
- };
587
-
588
- SourceGroup.prototype.addImagePreview = function(content, url, redraw) {
589
- var preview = {
590
- type: 'image',
591
- group: new Konva.Group({
592
- height: this._unwrappedHeight,
593
- listening: false
594
- })
595
- };
596
-
597
- var imageData = this._layer.getLoadedData(url);
598
-
599
- if (!imageData) {
600
- imageData = new Image();
601
-
602
- var self = this;
603
-
604
- imageData.onload = function() {
605
- self._layer.setLoadedData(url, this);
606
- preview.loaded = true;
607
- self._createImagePreview(preview, imageData, redraw);
608
- };
609
-
610
- imageData.src = content;
611
- }
612
- else {
613
- preview.loaded = true;
614
- this._createImagePreview(preview, imageData, redraw);
615
- }
616
- };
617
-
618
- SourceGroup.prototype.addVideoPreview = function(content, url, redraw) {
619
- var preview = {
620
- type: 'video',
621
- group: new Konva.Group({
622
- y: this._source.binaryUrl && this._source.previewUrl ? this._source.binaryHeight : 0,
623
- height: this._source.binaryUrl && this._source.previewUrl ?
624
- this._source.previewHeight : this._unwrappedHeight,
625
- listening: false
626
- })
627
- };
628
-
629
- var imageData = this._layer.getLoadedData(url);
630
-
631
- if (!imageData) {
632
- var video = document.createElement('video');
633
- var self = this;
634
-
635
- video.onloadeddata = function() {
636
- this.currentTime = this.duration / 2;
637
-
638
- var canvas = document.createElement('canvas');
639
-
640
- canvas.width = this.videoWidth;
641
- canvas.height = this.videoHeight;
642
- canvas.getContext('2d').drawImage(this, 0, 0, canvas.width, canvas.height);
643
-
644
- imageData = new Image();
645
-
646
- imageData.onload = function() {
647
- self._layer.setLoadedData(url, this);
648
- preview.loaded = true;
649
- self._createImagePreview(preview, imageData, redraw);
650
- };
651
-
652
- imageData.src = canvas.toDataURL();
653
- };
654
-
655
- video.src = content;
656
- }
657
- else {
658
- preview.loaded = true;
659
- this._createImagePreview(preview, imageData, redraw);
660
- }
661
- };
662
-
663
- SourceGroup.prototype.addAudioPreview = function(type, content, url, redraw) {
664
- var preview = {
665
- type: 'audio',
666
- group: new Konva.Group({
667
- height: this._source.binaryUrl && this._source.previewUrl ?
668
- this._source.binaryHeight : this._unwrappedHeight,
669
- listening: false
670
- }),
671
- url: url
672
- };
673
-
674
- var self = this;
675
-
676
- var audioData = this._layer.getLoadedData(url);
677
-
678
- if (!audioData) {
679
- var waveformBuilder = new WaveformBuilder(this._peaks);
680
- var options = Object.assign({},this._peaks.options);
681
-
682
- if (type === 'audio') {
683
- options.objectUrl = content;
684
- }
685
- else {
686
- options.dataUri = content;
687
- }
688
-
689
- waveformBuilder.init(options, function(err, originalWaveformData) {
690
- if (err) {
691
- throw err;
692
- }
693
-
694
- originalWaveformData.hasAudio = self._hasAudio(originalWaveformData);
695
-
696
- if (originalWaveformData.hasAudio) {
697
- var newScale = originalWaveformData.sample_rate / self._view.getTimeToPixelsMaxZoom();
698
-
699
- if (newScale > originalWaveformData.scale) {
700
- self._minScale = newScale;
701
- }
702
- else {
703
- self._minScale = originalWaveformData.scale;
704
- }
705
-
706
- self._view.setTimeToPixelsMaxZoom(originalWaveformData.sample_rate / self._minScale);
707
- }
708
-
709
- self._layer.setLoadedData(url, originalWaveformData);
710
- self._layer.setLoadedData(
711
- url + '-scaled',
712
- { data: originalWaveformData, scale: originalWaveformData.sample_rate / self._minScale }
713
- );
714
- preview.loaded = true;
715
- self._createAudioPreview(preview, originalWaveformData, redraw);
716
- });
717
- }
718
- else {
719
- preview.loaded = true;
720
- this._createAudioPreview(preview, audioData, redraw);
721
- }
722
- };
723
-
724
- SourceGroup.prototype._hasAudio = function(waveformData) {
725
- var channels = waveformData.channels;
726
- var channel, someIsNotZero = false;
727
-
728
- for (var i = 0; i < channels; i++) {
729
- channel = waveformData.channel(i);
730
-
731
- someIsNotZero = channel.min_array().some(function(item) {
732
- return item !== 0;
733
- });
734
-
735
- if (!someIsNotZero) {
736
- someIsNotZero = channel.max_array().some(function(item) {
737
- return item !== 0;
738
- });
739
- }
740
-
741
- if (someIsNotZero) {
742
- break;
743
- }
744
- }
745
-
746
- return someIsNotZero;
747
- };
748
-
749
- SourceGroup.prototype._createAudioPreview = function(preview, waveformData, redraw) {
750
- if (waveformData.hasAudio) {
751
- var waveform = new WaveformShape({
752
- layer: this._layer,
753
- view: this._view,
754
- color: this._peaks.options.zoomWaveformColor,
755
- source: this._source,
756
- height: preview.group.height(),
757
- url: preview.url
758
- });
759
-
760
- preview.group.add(waveform);
761
- this._unwrap.add(preview.group);
762
-
763
- if (redraw) {
764
- this._layer.rescale(true);
765
- }
766
-
767
- this._previewList.push(preview);
768
- }
769
- };
770
-
771
- SourceGroup.prototype.getAudioPreview = function() {
772
- return this._previewList.filter(function(preview) {
773
- return preview.type === 'audio';
774
- });
775
- };
776
-
777
- SourceGroup.prototype.setSelected = function(isSelected) {
778
- // update unwrap
779
- var background = this._unwrap.getChildren(function(node) {
780
- return node.getClassName() === 'Shape';
781
- });
782
-
783
- if (background) {
784
- if (isSelected) {
785
- background.stroke(this._source.selectedColor);
786
- background.strokeWidth(SELECTED_BORDER_WIDTH);
787
- }
788
- else {
789
- background.stroke(this._source.borderColor);
790
- background.strokeWidth(this._source.borderWidth);
791
- }
792
- }
793
-
794
- // update wrap
795
- background = this._wrap.getChildren(function(node) {
796
- return node.getClassName() === 'Shape';
797
- });
798
-
799
- if (background) {
800
- if (isSelected) {
801
- background.stroke(this._source.selectedColor);
802
- background.strokeWidth(SELECTED_BORDER_WIDTH);
803
- }
804
- else {
805
- background.stroke(this._source.borderColor);
806
- background.strokeWidth(this._source.borderWidth);
807
- }
808
- }
809
-
810
- this._view.drawSourcesLayer();
811
- };
812
-
813
- SourceGroup.prototype.updatePreviews = function() {
814
- var self = this;
815
-
816
- this._previewList.forEach(function(preview) {
817
- if (preview.loaded) {
818
- switch (preview.type) {
819
- case 'video':
820
- case 'image':
821
- // image or video preview
822
- if (self._unwrappedHeight !== preview.imageData.referenceHeight) {
823
- preview.imageData.referenceHeight = preview.group.height();
824
- preview.imageData.borderSpacing = SPACING_BETWEEN_PREVIEW_AND_BORDER_RATIO
825
- * preview.imageData.referenceHeight;
826
- preview.imageData.height = preview.imageData.referenceHeight
827
- - (2 * preview.imageData.borderSpacing);
828
- preview.imageData.width = preview.imageData.height
829
- * preview.imageData.dimRatio;
830
- preview.imageData.imageSpacing = preview.imageData.width
831
- * SPACING_BETWEEN_PREVIEWS;
832
- }
833
-
834
- var interImageSpacing = preview.imageData.width + preview.imageData.imageSpacing;
835
- var imageNumber;
836
-
837
- if (self._width > preview.imageData.borderSpacing) {
838
- imageNumber = Math.trunc(
839
- (self._width - preview.imageData.borderSpacing)
840
- / interImageSpacing
841
- ) + 1;
842
- }
843
- else {
844
- imageNumber = 0;
845
- }
846
-
847
- var imageList = preview.group.getChildren();
848
-
849
- var i = 0;
850
-
851
- for (i = 0; i < imageNumber; i++) {
852
- if (imageList.length > i) {
853
- imageList[i].visible(true);
854
- }
855
- else {
856
- var imagePreview = new Konva.Image({
857
- x: preview.imageData.borderSpacing + i * interImageSpacing,
858
- y: preview.imageData.borderSpacing,
859
- image: preview.imageData.image,
860
- width: preview.imageData.width,
861
- height: preview.imageData.height,
862
- listening: false,
863
- visible: true
864
- });
865
-
866
- preview.group.add(imagePreview);
867
- }
868
- }
869
-
870
- for (i = imageNumber; i < imageList.length; i++) {
871
- imageList[i].visible(false);
872
- }
873
- }
874
- }
875
- });
876
- };
877
-
878
- SourceGroup.prototype._createImagePreview = function(preview, image, redraw) {
879
- preview.imageData = {
880
- image: image,
881
- referenceHeight: null,
882
- dimRatio: null,
883
- borderSpacing: null,
884
- height: null,
885
- width: null,
886
- imageSpacing: null
887
- };
888
-
889
- preview.imageData.referenceHeight = preview.group.height();
890
- preview.imageData.dimRatio = image.width / image.height;
891
- preview.imageData.borderSpacing = SPACING_BETWEEN_PREVIEW_AND_BORDER_RATIO
892
- * preview.imageData.referenceHeight;
893
- preview.imageData.height = preview.imageData.referenceHeight
894
- - (2 * preview.imageData.borderSpacing);
895
- preview.imageData.width = preview.imageData.height * preview.imageData.dimRatio;
896
- preview.imageData.imageSpacing = preview.imageData.width * SPACING_BETWEEN_PREVIEWS;
897
-
898
- var currentX = preview.imageData.borderSpacing;
899
-
900
- while (currentX < this._width) {
901
- var imagePreview = new Konva.Image({
902
- x: currentX,
903
- y: preview.imageData.borderSpacing,
904
- image: image,
905
- width: preview.imageData.width,
906
- height: preview.imageData.height,
907
- listening: false
908
- });
909
-
910
- preview.group.add(imagePreview);
911
-
912
- currentX += preview.imageData.width + preview.imageData.imageSpacing;
913
- }
914
-
915
- this._unwrap.add(preview.group);
916
-
917
- if (redraw) {
918
- this._group.draw();
919
- }
920
-
921
- this._previewList.push(preview);
922
- };
923
-
924
- SourceGroup.prototype.isWrapped = function() {
925
- return this._source.wrapped;
926
- };
927
-
928
- SourceGroup.prototype.getCurrentHeight = function() {
929
- return this._height;
930
- };
931
-
932
- SourceGroup.prototype.wrap = function(notify) {
933
- if (!this._wrap.visible()) {
934
- if (this._wrap) {
935
- this._wrap.visible(true);
936
- if (this._unwrap) {
937
- this._unwrap.visible(false);
938
- }
939
-
940
- this._source.wrapped = true;
941
-
942
- if (notify) {
943
- this._peaks.emit('source.wrappingChanged', this);
944
- }
945
- }
946
- }
947
- };
948
-
949
- SourceGroup.prototype.unwrap = function(notify) {
950
- if (!this._unwrap.visible()) {
951
- if (this._unwrap) {
952
- this._unwrap.visible(true);
953
- if (this._wrap) {
954
- this._wrap.visible(false);
955
- }
956
-
957
- this._source.wrapped = false;
958
-
959
- if (notify) {
960
- this._peaks.emit('source.wrappingChanged', this);
961
- }
962
- }
963
- }
964
- };
965
-
966
- SourceGroup.prototype.setVisible = function(boolean) {
967
- this._group.visible(boolean);
968
- };
969
-
970
- SourceGroup.prototype.setListening = function(boolean) {
971
- this._group.listening(boolean);
972
- };
973
-
974
- SourceGroup.prototype.isVisible = function() {
975
- return this._group.visible();
976
- };
977
-
978
- SourceGroup.prototype.isDragged = function() {
979
- return this._dragged;
980
- };
981
-
982
- SourceGroup.prototype.destroy = function() {
983
- this._group.destroy();
984
- };
985
-
986
- return SourceGroup;
987
- });
1
+ /**
2
+ * @file
3
+ *
4
+ * Defines the {@link SourceGroup} class.
5
+ *
6
+ * @module source-group
7
+ */
8
+
9
+ define([
10
+ './waveform-builder',
11
+ './waveform-shape',
12
+ './utils',
13
+ 'konva'
14
+ ], function(
15
+ WaveformBuilder,
16
+ WaveformShape,
17
+ Utils,
18
+ Konva) {
19
+ 'use strict';
20
+
21
+ var SPACING_BETWEEN_PREVIEW_AND_BORDER_RATIO = 0.15;
22
+ var SPACING_BETWEEN_PREVIEWS = 1.5;
23
+ var HANDLE_WIDTH = 8;
24
+ var CORNER_RADIUS = 8;
25
+ var SELECTED_BORDER_WIDTH = 6;
26
+
27
+ /**
28
+ * Creates a source group for the given source.
29
+ *
30
+ * @class
31
+ * @alias SourceGroup
32
+ *
33
+ * @param {Source} source
34
+ * @param {Peaks} peaks
35
+ * @param {SourcesLayer} layer
36
+ * @param {WaveformOverview|WaveformZoomView} view
37
+ */
38
+
39
+ function SourceGroup(source, peaks, layer, view) {
40
+ this._source = source;
41
+ this._peaks = peaks;
42
+ this._layer = layer;
43
+ this._view = view;
44
+
45
+ var self = this;
46
+
47
+ this._x = this._view.timeToPixels(source.startTime);
48
+ this._width = this._view.timeToPixels(source.endTime - source.startTime);
49
+ this._unwrappedHeight = source.binaryHeight && source.previewHeight ?
50
+ source.binaryHeight + source.previewHeight :
51
+ this._peaks.options.lineHeight;
52
+ this._wrappedHeight = this._peaks.options.wrappedLineHeight;
53
+
54
+ this._previewList = [];
55
+
56
+ this._group = new Konva.Group({
57
+ x: this._x,
58
+ draggable: this._source.draggable,
59
+ dragBoundFunc: function() {
60
+ return {
61
+ x: this.absolutePosition().x,
62
+ y: this.absolutePosition().y
63
+ };
64
+ },
65
+ clipFunc: function(ctx) {
66
+ self.drawSourceShape(ctx);
67
+ }
68
+ });
69
+
70
+ this._group.on('dragstart', this._onSourceGroupDragStart.bind(this));
71
+ this._group.on('mouseover', function() {
72
+ self._view.setHoveredElement(self);
73
+ if (self._view.getCurrentMode() === 'cut') {
74
+ self.toggleDragging(false);
75
+ self.toggleResizing(false);
76
+ }
77
+ });
78
+ this._group.on('mouseout', function() {
79
+ self._view.setHoveredElement(null);
80
+ if (self._view.getCurrentMode() === 'cut') {
81
+ self.toggleDragging(true);
82
+ self.toggleResizing(true);
83
+ }
84
+ });
85
+ this._group.on('dragend', this._onSourceGroupDragEnd.bind(this));
86
+
87
+ this._addWrap(true);
88
+ this._addUnwrap(true);
89
+ this._addHandles(true);
90
+
91
+ this.setWrapping(source.wrapped);
92
+ }
93
+
94
+ // SourceGroup.prototype.rescale = function() {
95
+ // this.update();
96
+
97
+ // this._previewList.forEach(function(preview) {
98
+ // if (preview.loaded) {
99
+ // switch (preview.type) {
100
+ // case 'audio':
101
+ // preview.group.getChildren()[0].rescale(true);
102
+ // break;
103
+ // case 'video':
104
+ // case 'image':
105
+ // default:
106
+ // // No resampling
107
+ // }
108
+ // }
109
+ // });
110
+ // };
111
+
112
+ SourceGroup.prototype._onSourceGroupDragStart = function() {
113
+ this._dragged = true;
114
+ this._mouseDownX = this._view.getPointerPosition().x;
115
+ this._initialStartTime = this._source.startTime;
116
+ this._initialStartPixel = this._view.timeToPixels(this._initialStartTime);
117
+ this._initialEndTime = this._source.endTime;
118
+ this._initialEndPixel = this._view.timeToPixels(this._initialEndTime);
119
+ this._initialFrameOffset = this._view.getFrameOffset();
120
+ };
121
+
122
+ SourceGroup.prototype._onSourceGroupDragEnd = function() {
123
+ this._dragged = false;
124
+ this._view.updateTimelineLength();
125
+ this._peaks.emit('sources.updated');
126
+ };
127
+
128
+ SourceGroup.prototype._onSourceGroupDrag = function(draggedElement) {
129
+ var self = this;
130
+
131
+ var pos = this._view.updateWithAutoScroll(
132
+ draggedElement,
133
+ function() {
134
+ var mousePos = Math.min(
135
+ self._view.getWidth() - self._peaks.options.autoScrollThreshold * self._view.getWidth(),
136
+ Math.max(
137
+ 0,
138
+ self._view.getPointerPosition().x
139
+ )
140
+ );
141
+
142
+ var diff = mousePos - self._mouseDownX;
143
+
144
+ self._layer.updateSource(
145
+ self._source,
146
+ self._initialStartPixel + diff + (self._view.getFrameOffset() - self._initialFrameOffset),
147
+ self._initialEndPixel + diff + (self._view.getFrameOffset() - self._initialFrameOffset),
148
+ self._view.getPointerPosition().y
149
+ );
150
+
151
+ self._view.setTimelineLength(
152
+ self._view.timeToPixels(self._source.endTime) + self._view.getWidth()
153
+ );
154
+ }
155
+ );
156
+
157
+ return {
158
+ x: pos.x,
159
+ y: pos.y
160
+ };
161
+ };
162
+
163
+ SourceGroup.prototype._onSourceGroupHandleDrag = function(draggedElement, dragPos, leftHandle) {
164
+ var self = this;
165
+
166
+ var pos = this._view.updateWithAutoScroll(
167
+ draggedElement,
168
+ function() {
169
+ self._layer.updateSource(
170
+ self._source,
171
+ leftHandle ? dragPos.x + self._view.getFrameOffset() : null,
172
+ leftHandle ? null : dragPos.x + draggedElement.width() + self._view.getFrameOffset()
173
+ );
174
+ }
175
+ );
176
+
177
+ this._view.setTimelineLength(
178
+ this._view.timeToPixels(this._source.endTime) + this._view.getWidth()
179
+ );
180
+
181
+ return {
182
+ x: pos.x,
183
+ y: pos.y
184
+ };
185
+ };
186
+
187
+ SourceGroup.prototype.update = function() {
188
+ var startPixel = this._view.timeToPixels(this._source.startTime);
189
+ var endPixel = this._view.timeToPixels(this._source.endTime);
190
+ var frameOffset = this._view.timeToPixels(this._view.getTimeOffset());
191
+
192
+ this._group.x(startPixel - frameOffset);
193
+
194
+ this._x = startPixel;
195
+
196
+ var newWidth = endPixel - startPixel;
197
+
198
+ if (newWidth !== this._width) {
199
+ this._width = newWidth;
200
+
201
+ // update handles
202
+ this._rightHandle.x(newWidth - HANDLE_WIDTH);
203
+
204
+ // update unwrap
205
+ this.updatePreviews();
206
+
207
+ // update wrap
208
+ var title = this._wrap.getChildren(function(node) {
209
+ return node.getClassName() === 'Text';
210
+ });
211
+
212
+ if (title) {
213
+ title.width(newWidth - 10);
214
+ }
215
+ }
216
+ };
217
+
218
+ SourceGroup.prototype.setWrapping = function(wrap) {
219
+ if (wrap) {
220
+ this.wrap();
221
+ this._height = this._wrappedHeight;
222
+ }
223
+ else {
224
+ this.unwrap();
225
+ this._height = this._unwrappedHeight;
226
+ }
227
+
228
+ this.setHandlesWrapping(wrap);
229
+ };
230
+
231
+ SourceGroup.prototype.setHandlesWrapping = function(wrap) {
232
+ if (wrap) {
233
+ this._leftHandle.height(this._wrappedHeight);
234
+ this._rightHandle.height(this._wrappedHeight);
235
+ }
236
+ else {
237
+ this._leftHandle.height(this._unwrappedHeight);
238
+ this._rightHandle.height(this._unwrappedHeight);
239
+ }
240
+ };
241
+
242
+ SourceGroup.prototype._addHandles = function(forceCreate) {
243
+ var self = this;
244
+
245
+ if (!this._leftHandle || forceCreate) {
246
+ this._leftHandle = new Konva.Rect({
247
+ x: 0,
248
+ width: HANDLE_WIDTH,
249
+ height: this._unwrappedHeight,
250
+ visible: true,
251
+ draggable: this._source.resizable,
252
+ dragBoundFunc: function(pos) {
253
+ return self._onSourceGroupHandleDrag(this, pos, true);
254
+ }
255
+ });
256
+
257
+ if (this._source.resizable) {
258
+ this._leftHandle.on('dragend', function() {
259
+ if (this._scrollingInterval) {
260
+ clearInterval(this._scrollingInterval);
261
+ this._scrollingInterval = null;
262
+ }
263
+ });
264
+
265
+ this._leftHandle.on('mouseover', function() {
266
+ self._view.setCursor('ew-resize');
267
+ });
268
+
269
+ this._leftHandle.on('mouseout', function() {
270
+ self._view.setCursor('default');
271
+ });
272
+ }
273
+ }
274
+
275
+ if (!this._rightHandle || forceCreate) {
276
+ this._rightHandle = new Konva.Rect({
277
+ x: this._width - HANDLE_WIDTH,
278
+ width: HANDLE_WIDTH,
279
+ height: this._unwrappedHeight,
280
+ visible: true,
281
+ draggable: this._source.resizable,
282
+ dragBoundFunc: function(pos) {
283
+ return self._onSourceGroupHandleDrag(this, pos, false);
284
+ }
285
+ });
286
+
287
+ if (this._source.resizable) {
288
+ this._rightHandle.on('dragend', function() {
289
+ if (this._scrollingInterval) {
290
+ clearInterval(this._scrollingInterval);
291
+ this._scrollingInterval = null;
292
+ }
293
+ });
294
+
295
+ this._rightHandle.on('mouseover', function() {
296
+ self._view.setCursor('ew-resize');
297
+ });
298
+
299
+ this._rightHandle.on('mouseout', function() {
300
+ self._view.setCursor('default');
301
+ });
302
+ }
303
+ }
304
+
305
+ this._group.add(this._leftHandle);
306
+ this._group.add(this._rightHandle);
307
+ };
308
+
309
+ SourceGroup.prototype._addUnwrap = function(forceCreate) {
310
+ if (!this._unwrap || forceCreate) {
311
+ this._unwrap = this._createUnwrap();
312
+ this._unwrap.visible(false);
313
+ }
314
+
315
+ this._group.add(this._unwrap);
316
+ };
317
+
318
+ SourceGroup.prototype.toggleDragging = function(bool) {
319
+ var background;
320
+
321
+ if (this._wrap) {
322
+ background = this._wrap.getChildren(function(node) {
323
+ return node.getClassName() === 'Shape';
324
+ });
325
+
326
+ if (background) {
327
+ background.draggable(bool);
328
+ }
329
+ }
330
+ if (this._unwrap) {
331
+ background = this._unwrap.getChildren(function(node) {
332
+ return node.getClassName() === 'Shape';
333
+ });
334
+
335
+ if (background) {
336
+ background.draggable(bool);
337
+ }
338
+ }
339
+ };
340
+
341
+ SourceGroup.prototype.toggleResizing = function(bool) {
342
+ if (this._leftHandle) {
343
+ this._leftHandle.draggable(bool);
344
+ }
345
+ if (this._rightHandle) {
346
+ this._rightHandle.draggable(bool);
347
+ }
348
+ };
349
+
350
+ SourceGroup.prototype.drawSourceShape = function(ctx, shape) {
351
+ var radius = Math.max(
352
+ 1,
353
+ Math.min(
354
+ this._width / 2,
355
+ Math.min(
356
+ CORNER_RADIUS,
357
+ this._height / 2
358
+ )
359
+ )
360
+ );
361
+ var x = Math.max(
362
+ 0,
363
+ this._view.getFrameOffset() - this._x - radius
364
+ );
365
+ var width = Math.min(
366
+ this._width - x,
367
+ this._view.getOriginalWidth() + radius - Math.max(
368
+ 0,
369
+ this._x - this._view.getFrameOffset()
370
+ )
371
+ );
372
+ var xWidth = x + width;
373
+
374
+ ctx.beginPath();
375
+ ctx.moveTo(x + radius, 0);
376
+ ctx.lineTo(xWidth - radius, 0);
377
+ ctx.quadraticCurveTo(xWidth, 0, xWidth, radius);
378
+ ctx.lineTo(xWidth, this._height - radius);
379
+ ctx.quadraticCurveTo(xWidth, this._height, xWidth - radius, this._height);
380
+ ctx.lineTo(x + radius, this._height);
381
+ ctx.quadraticCurveTo(x, this._height, x, this._height - radius);
382
+ ctx.lineTo(x, radius);
383
+ ctx.quadraticCurveTo(x, 0, x + radius, 0);
384
+ ctx.closePath();
385
+
386
+ if (shape) {
387
+ ctx.fillStrokeShape(shape);
388
+ }
389
+ };
390
+
391
+ SourceGroup.prototype._createUnwrap = function() {
392
+ var unwrap = new Konva.Group({
393
+ width: this._width,
394
+ height: this._unwrappedHeight,
395
+ draggable: this._source.draggable,
396
+ dragBoundFunc: function() {
397
+ return {
398
+ x: this.absolutePosition().x,
399
+ y: this.absolutePosition().y
400
+ };
401
+ }
402
+ });
403
+
404
+ var self = this;
405
+
406
+ var background = new Konva.Shape({
407
+ fill: this._source.color,
408
+ stroke: this._source.borderColor,
409
+ strokeWidth: this._source.borderWidth,
410
+ sceneFunc: function(ctx, shape) {
411
+ self.drawSourceShape(ctx, shape);
412
+ },
413
+ draggable: this._source.draggable,
414
+ dragBoundFunc: function() {
415
+ return self._onSourceGroupDrag(this);
416
+ }
417
+ });
418
+
419
+ if (this._source.draggable) {
420
+ background.on('mouseenter', function() {
421
+ self._view.setCursor('pointer');
422
+ });
423
+ background.on('mouseout', function() {
424
+ self._view.setCursor('default');
425
+ });
426
+
427
+ background.on('dragstart', function() {
428
+ this._scrollInterval = null;
429
+ });
430
+
431
+ background.on('dragend', function() {
432
+ if (this._scrollingInterval) {
433
+ clearInterval(this._scrollingInterval);
434
+ this._scrollingInterval = null;
435
+ }
436
+ });
437
+ }
438
+
439
+ unwrap.add(background);
440
+
441
+ return unwrap;
442
+ };
443
+
444
+ SourceGroup.prototype._addWrap = function(forceCreate) {
445
+ if (!this._wrap || forceCreate) {
446
+ this._wrap = this._createWrap();
447
+ this._wrap.visible(false);
448
+ }
449
+
450
+ this._group.add(this._wrap);
451
+ };
452
+
453
+ SourceGroup.prototype._createWrap = function() {
454
+ var wrap = new Konva.Group({
455
+ width: this._width,
456
+ height: this._wrappedHeight,
457
+ draggable: this._source.draggable,
458
+ dragBoundFunc: function() {
459
+ return {
460
+ x: this.absolutePosition().x,
461
+ y: this.absolutePosition().y
462
+ };
463
+ }
464
+ });
465
+
466
+ var self = this;
467
+
468
+ var background = new Konva.Shape({
469
+ fill: this._source.color,
470
+ stroke: this._source.borderColor,
471
+ strokeWidth: this._source.borderWidth,
472
+ sceneFunc: function(ctx, shape) {
473
+ self.drawSourceShape(ctx, shape);
474
+ },
475
+ draggable: this._source.draggable,
476
+ dragBoundFunc: function() {
477
+ return self._onSourceGroupDrag(this);
478
+ }
479
+ });
480
+
481
+ if (this._source.draggable) {
482
+ background.on('mouseenter', function() {
483
+ self._view.setCursor('pointer');
484
+ });
485
+ background.on('mouseout', function() {
486
+ self._view.setCursor('default');
487
+ });
488
+
489
+ background.on('dragstart', function() {
490
+ this._scrollInterval = null;
491
+ });
492
+
493
+ background.on('dragend', function() {
494
+ if (this._scrollingInterval) {
495
+ clearInterval(this._scrollingInterval);
496
+ this._scrollingInterval = null;
497
+ }
498
+ });
499
+ }
500
+
501
+ var title = new Konva.Text({
502
+ x: 5,
503
+ width: this._width - 10,
504
+ height: this._wrappedHeight,
505
+ text: Utils.removeLineBreaks(this._source.title),
506
+ textAlign: 'left',
507
+ verticalAlign: 'middle',
508
+ fontSize: 14,
509
+ fontFamily: 'Open Sans',
510
+ fill: this._source.textColor,
511
+ wrap: 'none',
512
+ ellipsis: true,
513
+ listening: false
514
+ });
515
+
516
+ wrap.add(background);
517
+ wrap.add(title);
518
+
519
+ return wrap;
520
+ };
521
+
522
+ SourceGroup.prototype.getWidth = function() {
523
+ return this._width;
524
+ };
525
+
526
+ SourceGroup.prototype.getX = function() {
527
+ return this._x;
528
+ };
529
+
530
+ SourceGroup.prototype.getY = function() {
531
+ return this._group.absolutePosition().y;
532
+ };
533
+
534
+ SourceGroup.prototype.x = function(value) {
535
+ if (value) {
536
+ return this._group.x(value);
537
+ }
538
+ else {
539
+ return this._group.x();
540
+ }
541
+ };
542
+
543
+ SourceGroup.prototype.y = function(value) {
544
+ if (value) {
545
+ return this._group.y(value);
546
+ }
547
+ else {
548
+ return this._group.y();
549
+ }
550
+ };
551
+
552
+ SourceGroup.prototype.getSource = function() {
553
+ return this._source;
554
+ };
555
+
556
+ SourceGroup.prototype.startDrag = function() {
557
+ return this._group.startDrag();
558
+ };
559
+
560
+ SourceGroup.prototype.stopDrag = function() {
561
+ return this._group.stopDrag();
562
+ };
563
+
564
+ SourceGroup.prototype.addToGroup = function(group) {
565
+ group.add(this._group);
566
+ };
567
+
568
+ SourceGroup.prototype.isDescendantOf = function(group) {
569
+ group.isAncestorOf(this._group);
570
+ };
571
+
572
+ SourceGroup.prototype.moveTo = function(group) {
573
+ this._group.moveTo(group);
574
+ };
575
+
576
+ SourceGroup.prototype.getParent = function() {
577
+ return this._group.getParent();
578
+ };
579
+
580
+ SourceGroup.prototype.remove = function() {
581
+ this._group.remove();
582
+ };
583
+
584
+ SourceGroup.prototype.add = function(element) {
585
+ this._group.add(element);
586
+ };
587
+
588
+ SourceGroup.prototype.addImagePreview = function(content, url, redraw) {
589
+ var preview = {
590
+ type: 'image',
591
+ group: new Konva.Group({
592
+ height: this._unwrappedHeight,
593
+ listening: false
594
+ })
595
+ };
596
+
597
+ var imageData = this._layer.getLoadedData(url);
598
+
599
+ if (!imageData) {
600
+ imageData = new Image();
601
+
602
+ var self = this;
603
+
604
+ imageData.onload = function() {
605
+ self._layer.setLoadedData(url, this);
606
+ preview.loaded = true;
607
+ self._createImagePreview(preview, imageData, redraw);
608
+ };
609
+
610
+ imageData.src = content;
611
+ }
612
+ else {
613
+ preview.loaded = true;
614
+ this._createImagePreview(preview, imageData, redraw);
615
+ }
616
+ };
617
+
618
+ SourceGroup.prototype.addVideoPreview = function(content, url, redraw) {
619
+ var preview = {
620
+ type: 'video',
621
+ group: new Konva.Group({
622
+ y: this._source.binaryUrl && this._source.previewUrl ? this._source.binaryHeight : 0,
623
+ height: this._source.binaryUrl && this._source.previewUrl ?
624
+ this._source.previewHeight : this._unwrappedHeight,
625
+ listening: false
626
+ })
627
+ };
628
+
629
+ var imageData = this._layer.getLoadedData(url);
630
+
631
+ if (!imageData) {
632
+ var video = document.createElement('video');
633
+ var self = this;
634
+
635
+ video.onloadeddata = function() {
636
+ this.currentTime = this.duration / 2;
637
+
638
+ var canvas = document.createElement('canvas');
639
+
640
+ canvas.width = this.videoWidth;
641
+ canvas.height = this.videoHeight;
642
+ canvas.getContext('2d').drawImage(this, 0, 0, canvas.width, canvas.height);
643
+
644
+ imageData = new Image();
645
+
646
+ imageData.onload = function() {
647
+ self._layer.setLoadedData(url, this);
648
+ preview.loaded = true;
649
+ self._createImagePreview(preview, imageData, redraw);
650
+ };
651
+
652
+ imageData.src = canvas.toDataURL();
653
+ };
654
+
655
+ video.src = content;
656
+ }
657
+ else {
658
+ preview.loaded = true;
659
+ this._createImagePreview(preview, imageData, redraw);
660
+ }
661
+ };
662
+
663
+ SourceGroup.prototype.addAudioPreview = function(type, content, url, redraw) {
664
+ var preview = {
665
+ type: 'audio',
666
+ group: new Konva.Group({
667
+ height: this._source.binaryUrl && this._source.previewUrl ?
668
+ this._source.binaryHeight : this._unwrappedHeight,
669
+ listening: false
670
+ }),
671
+ url: url
672
+ };
673
+
674
+ var self = this;
675
+
676
+ var audioData = this._layer.getLoadedData(url);
677
+
678
+ if (!audioData) {
679
+ var waveformBuilder = new WaveformBuilder(this._peaks);
680
+ var options = Object.assign({},this._peaks.options);
681
+
682
+ if (type === 'audio') {
683
+ options.objectUrl = content;
684
+ }
685
+ else {
686
+ options.dataUri = content;
687
+ }
688
+
689
+ waveformBuilder.init(options, function(err, originalWaveformData) {
690
+ if (err) {
691
+ throw err;
692
+ }
693
+
694
+ originalWaveformData.hasAudio = self._hasAudio(originalWaveformData);
695
+
696
+ if (originalWaveformData.hasAudio) {
697
+ var newScale = originalWaveformData.sample_rate / self._view.getTimeToPixelsMaxZoom();
698
+
699
+ if (newScale > originalWaveformData.scale) {
700
+ self._minScale = newScale;
701
+ }
702
+ else {
703
+ self._minScale = originalWaveformData.scale;
704
+ }
705
+
706
+ self._view.setTimeToPixelsMaxZoom(originalWaveformData.sample_rate / self._minScale);
707
+ }
708
+
709
+ self._layer.setLoadedData(url, originalWaveformData);
710
+ self._layer.setLoadedData(
711
+ url + '-scaled',
712
+ { data: originalWaveformData, scale: originalWaveformData.sample_rate / self._minScale }
713
+ );
714
+ preview.loaded = true;
715
+ self._createAudioPreview(preview, originalWaveformData, redraw);
716
+ });
717
+ }
718
+ else {
719
+ preview.loaded = true;
720
+ this._createAudioPreview(preview, audioData, redraw);
721
+ }
722
+ };
723
+
724
+ SourceGroup.prototype._hasAudio = function(waveformData) {
725
+ var channels = waveformData.channels;
726
+ var channel, someIsNotZero = false;
727
+
728
+ for (var i = 0; i < channels; i++) {
729
+ channel = waveformData.channel(i);
730
+
731
+ someIsNotZero = channel.min_array().some(function(item) {
732
+ return item !== 0;
733
+ });
734
+
735
+ if (!someIsNotZero) {
736
+ someIsNotZero = channel.max_array().some(function(item) {
737
+ return item !== 0;
738
+ });
739
+ }
740
+
741
+ if (someIsNotZero) {
742
+ break;
743
+ }
744
+ }
745
+
746
+ return someIsNotZero;
747
+ };
748
+
749
+ SourceGroup.prototype._createAudioPreview = function(preview, waveformData, redraw) {
750
+ if (waveformData.hasAudio) {
751
+ var waveform = new WaveformShape({
752
+ layer: this._layer,
753
+ view: this._view,
754
+ color: this._peaks.options.zoomWaveformColor,
755
+ source: this._source,
756
+ height: preview.group.height(),
757
+ url: preview.url
758
+ });
759
+
760
+ preview.group.add(waveform);
761
+ this._unwrap.add(preview.group);
762
+
763
+ if (redraw) {
764
+ this._layer.rescale(true);
765
+ }
766
+
767
+ this._previewList.push(preview);
768
+ }
769
+ };
770
+
771
+ SourceGroup.prototype.getAudioPreview = function() {
772
+ return this._previewList.filter(function(preview) {
773
+ return preview.type === 'audio';
774
+ });
775
+ };
776
+
777
+ SourceGroup.prototype.setSelected = function(isSelected) {
778
+ // update unwrap
779
+ var background = this._unwrap.getChildren(function(node) {
780
+ return node.getClassName() === 'Shape';
781
+ });
782
+
783
+ if (background) {
784
+ if (isSelected) {
785
+ background.stroke(this._source.selectedColor);
786
+ background.strokeWidth(SELECTED_BORDER_WIDTH);
787
+ }
788
+ else {
789
+ background.stroke(this._source.borderColor);
790
+ background.strokeWidth(this._source.borderWidth);
791
+ }
792
+ }
793
+
794
+ // update wrap
795
+ background = this._wrap.getChildren(function(node) {
796
+ return node.getClassName() === 'Shape';
797
+ });
798
+
799
+ if (background) {
800
+ if (isSelected) {
801
+ background.stroke(this._source.selectedColor);
802
+ background.strokeWidth(SELECTED_BORDER_WIDTH);
803
+ }
804
+ else {
805
+ background.stroke(this._source.borderColor);
806
+ background.strokeWidth(this._source.borderWidth);
807
+ }
808
+ }
809
+
810
+ this._view.drawSourcesLayer();
811
+ };
812
+
813
+ SourceGroup.prototype.updatePreviews = function() {
814
+ var self = this;
815
+
816
+ this._previewList.forEach(function(preview) {
817
+ if (preview.loaded) {
818
+ switch (preview.type) {
819
+ case 'video':
820
+ case 'image':
821
+ // image or video preview
822
+ if (self._unwrappedHeight !== preview.imageData.referenceHeight) {
823
+ preview.imageData.referenceHeight = preview.group.height();
824
+ preview.imageData.borderSpacing = SPACING_BETWEEN_PREVIEW_AND_BORDER_RATIO
825
+ * preview.imageData.referenceHeight;
826
+ preview.imageData.height = preview.imageData.referenceHeight
827
+ - (2 * preview.imageData.borderSpacing);
828
+ preview.imageData.width = preview.imageData.height
829
+ * preview.imageData.dimRatio;
830
+ preview.imageData.imageSpacing = preview.imageData.width
831
+ * SPACING_BETWEEN_PREVIEWS;
832
+ }
833
+
834
+ var interImageSpacing = preview.imageData.width + preview.imageData.imageSpacing;
835
+ var imageNumber;
836
+
837
+ if (self._width > preview.imageData.borderSpacing) {
838
+ imageNumber = Math.trunc(
839
+ (self._width - preview.imageData.borderSpacing)
840
+ / interImageSpacing
841
+ ) + 1;
842
+ }
843
+ else {
844
+ imageNumber = 0;
845
+ }
846
+
847
+ var imageList = preview.group.getChildren();
848
+
849
+ var i = 0;
850
+
851
+ for (i = 0; i < imageNumber; i++) {
852
+ if (imageList.length > i) {
853
+ imageList[i].visible(true);
854
+ }
855
+ else {
856
+ var imagePreview = new Konva.Image({
857
+ x: preview.imageData.borderSpacing + i * interImageSpacing,
858
+ y: preview.imageData.borderSpacing,
859
+ image: preview.imageData.image,
860
+ width: preview.imageData.width,
861
+ height: preview.imageData.height,
862
+ listening: false,
863
+ visible: true
864
+ });
865
+
866
+ preview.group.add(imagePreview);
867
+ }
868
+ }
869
+
870
+ for (i = imageNumber; i < imageList.length; i++) {
871
+ imageList[i].visible(false);
872
+ }
873
+ }
874
+ }
875
+ });
876
+ };
877
+
878
+ SourceGroup.prototype._createImagePreview = function(preview, image, redraw) {
879
+ preview.imageData = {
880
+ image: image,
881
+ referenceHeight: null,
882
+ dimRatio: null,
883
+ borderSpacing: null,
884
+ height: null,
885
+ width: null,
886
+ imageSpacing: null
887
+ };
888
+
889
+ preview.imageData.referenceHeight = preview.group.height();
890
+ preview.imageData.dimRatio = image.width / image.height;
891
+ preview.imageData.borderSpacing = SPACING_BETWEEN_PREVIEW_AND_BORDER_RATIO
892
+ * preview.imageData.referenceHeight;
893
+ preview.imageData.height = preview.imageData.referenceHeight
894
+ - (2 * preview.imageData.borderSpacing);
895
+ preview.imageData.width = preview.imageData.height * preview.imageData.dimRatio;
896
+ preview.imageData.imageSpacing = preview.imageData.width * SPACING_BETWEEN_PREVIEWS;
897
+
898
+ var currentX = preview.imageData.borderSpacing;
899
+
900
+ while (currentX < this._width) {
901
+ var imagePreview = new Konva.Image({
902
+ x: currentX,
903
+ y: preview.imageData.borderSpacing,
904
+ image: image,
905
+ width: preview.imageData.width,
906
+ height: preview.imageData.height,
907
+ listening: false
908
+ });
909
+
910
+ preview.group.add(imagePreview);
911
+
912
+ currentX += preview.imageData.width + preview.imageData.imageSpacing;
913
+ }
914
+
915
+ this._unwrap.add(preview.group);
916
+
917
+ if (redraw) {
918
+ this._group.draw();
919
+ }
920
+
921
+ this._previewList.push(preview);
922
+ };
923
+
924
+ SourceGroup.prototype.isWrapped = function() {
925
+ return this._source.wrapped;
926
+ };
927
+
928
+ SourceGroup.prototype.getCurrentHeight = function() {
929
+ return this._height;
930
+ };
931
+
932
+ SourceGroup.prototype.wrap = function(notify) {
933
+ if (!this._wrap.visible()) {
934
+ if (this._wrap) {
935
+ this._wrap.visible(true);
936
+ if (this._unwrap) {
937
+ this._unwrap.visible(false);
938
+ }
939
+
940
+ this._source.wrapped = true;
941
+
942
+ if (notify) {
943
+ this._peaks.emit('source.wrappingChanged', this);
944
+ }
945
+ }
946
+ }
947
+ };
948
+
949
+ SourceGroup.prototype.unwrap = function(notify) {
950
+ if (!this._unwrap.visible()) {
951
+ if (this._unwrap) {
952
+ this._unwrap.visible(true);
953
+ if (this._wrap) {
954
+ this._wrap.visible(false);
955
+ }
956
+
957
+ this._source.wrapped = false;
958
+
959
+ if (notify) {
960
+ this._peaks.emit('source.wrappingChanged', this);
961
+ }
962
+ }
963
+ }
964
+ };
965
+
966
+ SourceGroup.prototype.setVisible = function(boolean) {
967
+ this._group.visible(boolean);
968
+ };
969
+
970
+ SourceGroup.prototype.setListening = function(boolean) {
971
+ this._group.listening(boolean);
972
+ };
973
+
974
+ SourceGroup.prototype.isVisible = function() {
975
+ return this._group.visible();
976
+ };
977
+
978
+ SourceGroup.prototype.isDragged = function() {
979
+ return this._dragged;
980
+ };
981
+
982
+ SourceGroup.prototype.destroy = function() {
983
+ this._group.destroy();
984
+ };
985
+
986
+ return SourceGroup;
987
+ });