@checksub_team/peaks_timeline 2.0.0-alpha.15 → 2.0.0-alpha.17

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.
@@ -63,18 +63,18 @@ define([
63
63
  Axis.prototype._onPlayheadMoved = function(playheadX, playheadWidth) {
64
64
  this._maskStart = playheadX + this._view.getFrameOffset();
65
65
  this._maskEnd = playheadX + this._view.getFrameOffset() + playheadWidth;
66
- this._frontLayer.draw();
66
+ this._frontLayer.batchDraw();
67
67
  };
68
68
 
69
69
  Axis.prototype._onPlayheadHidden = function() {
70
70
  this._maskStart = null;
71
71
  this._maskEnd = null;
72
- this._frontLayer.draw();
72
+ this._frontLayer.batchDraw();
73
73
  };
74
74
 
75
- Axis.prototype.draw = function() {
76
- this._backLayer.draw();
77
- this._frontLayer.draw();
75
+ Axis.prototype.batchDraw = function() {
76
+ this._backLayer.batchDraw();
77
+ this._frontLayer.batchDraw();
78
78
  };
79
79
 
80
80
  Axis.prototype.addBackToStage = function(stage) {
@@ -86,12 +86,12 @@ define([
86
86
  if (self._options.draggable) {
87
87
  group.on('dragstart', function() {
88
88
  self._label.show();
89
- self._options.group.draw();
89
+ self._batchDraw();
90
90
  });
91
91
 
92
92
  group.on('dragend', function() {
93
93
  self._label.hide();
94
- self._options.group.draw();
94
+ self._batchDraw();
95
95
  });
96
96
  }
97
97
 
@@ -100,13 +100,13 @@ define([
100
100
  self._options.view.setCursor('ew-resize');
101
101
  self._label.show();
102
102
  self._group.moveToTop();
103
- self._options.view.drawSourcesLayer();
103
+ self._options.view.batchDrawSourcesLayer();
104
104
  });
105
105
 
106
106
  self._handle.on('mouseout touchend', function() {
107
107
  self._options.view.setCursor('default');
108
108
  self._label.hide();
109
- self._options.view.drawSourcesLayer();
109
+ self._options.view.batchDrawSourcesLayer();
110
110
  });
111
111
  }
112
112
  };
@@ -128,5 +128,14 @@ define([
128
128
  this._label.setText(Utils.formatTime(time, false));
129
129
  };
130
130
 
131
+ DefaultSegmentMarker.prototype._batchDraw = function() {
132
+ const group = this._options.group;
133
+ const layer = group && group.getLayer && group.getLayer();
134
+
135
+ if (layer && typeof layer.batchDraw === 'function') {
136
+ layer.batchDraw();
137
+ }
138
+ };
139
+
131
140
  return DefaultSegmentMarker;
132
141
  });
@@ -68,7 +68,7 @@ define([
68
68
 
69
69
  this._layer.add(this._separatingLine);
70
70
 
71
- this._layer.draw();
71
+ this._layer.batchDraw();
72
72
 
73
73
  this._isDragging = false;
74
74
  this._dragLineId = null;
@@ -172,7 +172,7 @@ define([
172
172
  indicator.getChildren().forEach(function(child) {
173
173
  child.fill(child.getAttr('selectedColor'));
174
174
  });
175
- self.draw();
175
+ self.batchDraw();
176
176
  self._stage.container().style.cursor = 'pointer';
177
177
  });
178
178
 
@@ -180,7 +180,7 @@ define([
180
180
  indicator.getChildren().forEach(function(child) {
181
181
  child.fill(child.getAttr('defaultColor'));
182
182
  });
183
- self.draw();
183
+ self.batchDraw();
184
184
  if (!self._isDragging) {
185
185
  self._stage.container().style.cursor = 'default';
186
186
  }
@@ -219,7 +219,8 @@ define([
219
219
  this._indicators[line.id] = {
220
220
  lineGroup: lineGroup,
221
221
  indicator: indicator,
222
- type: line.indicatorType
222
+ type: line.indicatorType,
223
+ text: line.indicatorText
223
224
  };
224
225
  }
225
226
  };
@@ -250,7 +251,7 @@ define([
250
251
  indicatorData.type = line.indicatorType;
251
252
  indicatorData.text = line.indicatorText;
252
253
 
253
- this.draw();
254
+ this.batchDraw();
254
255
  };
255
256
 
256
257
  LineIndicator.prototype.removeIndicator = function(lineId, keepInList) {
@@ -320,13 +321,13 @@ define([
320
321
  }
321
322
 
322
323
  if (anyChange) {
323
- this.draw();
324
+ this.batchDraw();
324
325
  }
325
326
  return anyChange;
326
327
  };
327
328
 
328
- LineIndicator.prototype.draw = function() {
329
- this._layer.draw();
329
+ LineIndicator.prototype.batchDraw = function() {
330
+ this._layer.batchDraw();
330
331
  };
331
332
 
332
333
  LineIndicator.prototype._onWindowMove = function(event) {
@@ -229,7 +229,7 @@ define([
229
229
  }
230
230
  else {
231
231
  this.deselectDifference([], true);
232
- this._view.drawSourcesLayer(); // Redraw sources layer to remove selection
232
+ this._view.batchDrawSourcesLayer(); // Redraw sources layer to remove selection
233
233
  }
234
234
  };
235
235
 
@@ -258,7 +258,7 @@ define([
258
258
  ModeLayer.prototype._onMouseEnterInCutMode = function() {
259
259
  this._cutGroup.visible(true);
260
260
 
261
- this._layer.draw();
261
+ this._layer.batchDraw();
262
262
  };
263
263
 
264
264
  ModeLayer.prototype._updateCursorTime = function(position) {
@@ -359,13 +359,13 @@ define([
359
359
  this._updateCursorTime(cuttingPosition);
360
360
  this._updateCuttingLine(cuttingPosition);
361
361
 
362
- this._layer.draw();
362
+ this._layer.batchDraw();
363
363
  };
364
364
 
365
365
  ModeLayer.prototype._onMouseLeaveInCutMode = function() {
366
366
  this._cutGroup.visible(false);
367
367
 
368
- this._layer.draw();
368
+ this._layer.batchDraw();
369
369
  };
370
370
 
371
371
  ModeLayer.prototype._onMouseClickInCutMode = function() {
@@ -417,7 +417,7 @@ define([
417
417
  this._updateCursorTime(cuttingPosition);
418
418
  this._updateCuttingLine(cuttingPosition);
419
419
 
420
- this._layer.draw();
420
+ this._layer.batchDraw();
421
421
  }
422
422
  }
423
423
  };
@@ -494,8 +494,8 @@ define([
494
494
  }
495
495
 
496
496
  this._mode = mode;
497
- this._layer.draw();
498
- this._view.drawSourcesLayer();
497
+ this._layer.batchDraw();
498
+ this._view.batchDrawSourcesLayer();
499
499
  };
500
500
 
501
501
  ModeLayer.prototype.getCurrentMode = function() {
@@ -269,7 +269,7 @@ define([
269
269
  }
270
270
 
271
271
  this._time = time;
272
- this._playheadLayer.draw();
272
+ this._playheadLayer.batchDraw();
273
273
  };
274
274
 
275
275
  /**
@@ -307,7 +307,7 @@ define([
307
307
  }
308
308
 
309
309
  if (updated) {
310
- this._playheadLayer.draw();
310
+ this._playheadLayer.batchDraw();
311
311
  }
312
312
  };
313
313
 
@@ -380,7 +380,7 @@ define([
380
380
  0.65, this._segment.warningColor
381
381
  ]);
382
382
 
383
- this._view.drawSourcesLayer();
383
+ this._view.batchDrawSourcesLayer();
384
384
 
385
385
  this._peaks.emit('segments.mouseenter', this._segment);
386
386
  };
@@ -400,7 +400,7 @@ define([
400
400
  0.65, this._segment.warningColor
401
401
  ]);
402
402
 
403
- this._view.drawSourcesLayer();
403
+ this._view.batchDrawSourcesLayer();
404
404
 
405
405
  this._peaks.emit('segments.mouseleave', this._segment);
406
406
  };
@@ -377,7 +377,7 @@ define([
377
377
  };
378
378
 
379
379
  SegmentsGroup.prototype._draw = function() {
380
- this._view.drawSourcesLayer();
380
+ this._view.batchDrawSourcesLayer();
381
381
  };
382
382
 
383
383
  /**
@@ -24,6 +24,7 @@ define([
24
24
  var SPACING_BETWEEN_PREVIEWS = 1.5;
25
25
  var CORNER_RADIUS = 8;
26
26
  var INDICATOR_RADIUS = 4; // px
27
+ var PREVIEW_CREATE_CHUNK = 8; // number of preview tiles to add per idle slice
27
28
 
28
29
  /**
29
30
  * Creates a source group for the given source.
@@ -60,6 +61,8 @@ define([
60
61
  this._isDragged = false;
61
62
 
62
63
  this._previewList = [];
64
+ // internal queue state for async preview creation
65
+ this._previewBuildQueue = new Set();
63
66
 
64
67
  this._markersGroup = this._createMarkers();
65
68
 
@@ -131,7 +134,7 @@ define([
131
134
  if (!this._source.loading) {
132
135
  this._showButtons();
133
136
  }
134
- this._group.draw();
137
+ this._batchDraw();
135
138
  };
136
139
 
137
140
  SourceGroup.prototype._onHoverEnd = function() {
@@ -139,7 +142,7 @@ define([
139
142
  this._manualHover = false;
140
143
  this._view.setHoveredElement(null);
141
144
  this._hideButtons();
142
- this._group.draw();
145
+ this._batchDraw();
143
146
  };
144
147
 
145
148
  SourceGroup.prototype._onDragStart = function(element) {
@@ -211,7 +214,7 @@ define([
211
214
  leftHandle ? start + diff + timeOffsetDiff : null,
212
215
  leftHandle ? null : end + diff + timeOffsetDiff
213
216
  )) {
214
- this._layer.draw();
217
+ this._layer.batchDraw();
215
218
  }
216
219
  }.bind(this)
217
220
  );
@@ -843,80 +846,49 @@ define([
843
846
  throw err;
844
847
  }
845
848
 
846
- originalWaveformData.hasAudio = self._hasAudio(originalWaveformData);
849
+ var newScale = originalWaveformData.sample_rate / self._view.getTimeToPixelsMaxZoom();
847
850
 
848
- if (originalWaveformData.hasAudio) {
849
- var newScale = originalWaveformData.sample_rate / self._view.getTimeToPixelsMaxZoom();
850
-
851
- if (newScale > originalWaveformData.scale) {
852
- self._minScale = newScale;
853
- }
854
- else {
855
- self._minScale = originalWaveformData.scale;
856
- }
857
-
858
- self._view.setTimeToPixelsMaxZoom(originalWaveformData.sample_rate / self._minScale);
851
+ if (newScale > originalWaveformData.scale) {
852
+ self._minScale = newScale;
853
+ }
854
+ else {
855
+ self._minScale = originalWaveformData.scale;
859
856
  }
860
857
 
858
+ self._view.setTimeToPixelsMaxZoom(originalWaveformData.sample_rate / self._minScale);
859
+
861
860
  self._layer.setLoadedData(url, originalWaveformData);
862
861
  self._layer.setLoadedData(
863
862
  url + '-scaled',
864
863
  { data: originalWaveformData, scale: originalWaveformData.sample_rate / self._minScale }
865
864
  );
866
865
  preview.loaded = true;
867
- self._createAudioPreview(preview, originalWaveformData, redraw);
866
+ self._createAudioPreview(preview, redraw);
868
867
  });
869
868
  }
870
869
  else {
871
870
  preview.loaded = true;
872
- this._createAudioPreview(preview, audioData, redraw);
871
+ this._createAudioPreview(preview, redraw);
873
872
  }
874
873
  };
875
874
 
876
- SourceGroup.prototype._hasAudio = function(waveformData) {
877
- var channels = waveformData.channels;
878
- var channel, someIsNotZero = false;
879
-
880
- for (var i = 0; i < channels; i++) {
881
- channel = waveformData.channel(i);
882
-
883
- someIsNotZero = channel.min_array().some(function(item) {
884
- return item !== 0;
885
- });
875
+ SourceGroup.prototype._createAudioPreview = function(preview, redraw) {
876
+ var waveform = new WaveformShape({
877
+ layer: this._layer,
878
+ view: this._view,
879
+ source: this._source,
880
+ height: preview.group.height(),
881
+ url: preview.url
882
+ });
886
883
 
887
- if (!someIsNotZero) {
888
- someIsNotZero = channel.max_array().some(function(item) {
889
- return item !== 0;
890
- });
891
- }
884
+ preview.group.add(waveform);
885
+ this._addToUnwrap(preview.group);
892
886
 
893
- if (someIsNotZero) {
894
- break;
895
- }
887
+ if (redraw) {
888
+ this._layer.rescale(true);
896
889
  }
897
890
 
898
- return someIsNotZero;
899
- };
900
-
901
- SourceGroup.prototype._createAudioPreview = function(preview, waveformData, redraw) {
902
- if (waveformData.hasAudio) {
903
- var waveform = new WaveformShape({
904
- layer: this._layer,
905
- view: this._view,
906
- source: this._source,
907
- height: preview.group.height(),
908
- url: preview.url
909
- });
910
-
911
- preview.group.add(waveform);
912
- this._addToUnwrap(preview.group);
913
-
914
- if (redraw) {
915
- this._layer.rescale(true);
916
- }
917
-
918
- this._previewList.push(preview);
919
- }
891
+ this._previewList.push(preview);
920
892
  };
921
893
 
922
894
  SourceGroup.prototype.getAudioPreview = function() {
@@ -1008,37 +980,100 @@ define([
1008
980
  imageNumber = 0;
1009
981
  }
1010
982
 
1011
- var imageList = preview.group.getChildren();
1012
-
1013
- var i = 0;
1014
-
1015
- for (i = 0; i < imageNumber; i++) {
1016
- if (imageList.length > i) {
1017
- imageList[i].visible(true);
1018
- }
1019
- else {
1020
- var imagePreview = new Konva.Image({
1021
- x: preview.imageData.borderSpacing + i * interImageSpacing,
1022
- y: preview.imageData.borderSpacing,
1023
- image: preview.imageData.image,
1024
- width: preview.imageData.width,
1025
- height: preview.imageData.height,
1026
- listening: false,
1027
- visible: true
1028
- });
1029
-
1030
- preview.group.add(imagePreview);
1031
- }
1032
- }
1033
-
1034
- for (i = imageNumber; i < imageList.length; i++) {
1035
- imageList[i].visible(false);
1036
- }
983
+ self._ensureImagePreviewCount(preview, imageNumber, interImageSpacing);
1037
984
  }
1038
985
  }
1039
986
  });
1040
987
  };
1041
988
 
989
+ SourceGroup.prototype._batchDraw = function() {
990
+ var layer = this._group && this._group.getLayer && this._group.getLayer();
991
+
992
+ if (layer && typeof layer.batchDraw === 'function') {
993
+ layer.batchDraw();
994
+ }
995
+ };
996
+
997
+ // Utility to schedule work during idle time or next frame
998
+ SourceGroup.prototype._scheduleIdle = function(fn) {
999
+ if (typeof window !== 'undefined' && window.requestIdleCallback) {
1000
+ return window.requestIdleCallback(fn, { timeout: 50 });
1001
+ }
1002
+
1003
+ if (typeof window !== 'undefined' && window.requestAnimationFrame) {
1004
+ return window.requestAnimationFrame(function() {
1005
+ fn({
1006
+ timeRemaining: function() {
1007
+ return 0;
1008
+ },
1009
+ didTimeout: true
1010
+ });
1011
+ });
1012
+ }
1013
+
1014
+ return setTimeout(function() {
1015
+ fn({
1016
+ timeRemaining: function() {
1017
+ return 0;
1018
+ },
1019
+ didTimeout: true
1020
+ });
1021
+ }, 0);
1022
+ };
1023
+
1024
+ SourceGroup.prototype._ensureImagePreviewCount = function(preview, targetCount, interImageSpacing) {
1025
+ var imageList = preview.group.getChildren();
1026
+ var currentCount = imageList.length;
1027
+
1028
+ for (var i = 0; i < Math.min(currentCount, targetCount); i++) {
1029
+ imageList[i].visible(true);
1030
+ }
1031
+ for (var j = targetCount; j < currentCount; j++) {
1032
+ imageList[j].visible(false);
1033
+ }
1034
+
1035
+ if (currentCount >= targetCount || this._previewBuildQueue.has(preview)) {
1036
+ this._batchDraw();
1037
+ return;
1038
+ }
1039
+
1040
+ this._previewBuildQueue.add(preview);
1041
+
1042
+ var self = this;
1043
+ var nextIndex = currentCount;
1044
+
1045
+ function buildChunk() {
1046
+ var added = 0;
1047
+
1048
+ while (nextIndex < targetCount && added < PREVIEW_CREATE_CHUNK) {
1049
+ var imagePreview = new Konva.Image({
1050
+ x: preview.imageData.borderSpacing + nextIndex * interImageSpacing,
1051
+ y: preview.imageData.borderSpacing,
1052
+ image: preview.imageData.image,
1053
+ width: preview.imageData.width,
1054
+ height: preview.imageData.height,
1055
+ listening: false,
1056
+ visible: true
1057
+ });
1058
+
1059
+ preview.group.add(imagePreview);
1060
+ nextIndex += 1;
1061
+ added += 1;
1062
+ }
1063
+
1064
+ self._batchDraw();
1065
+
1066
+ if (nextIndex < targetCount) {
1067
+ self._scheduleIdle(buildChunk);
1068
+ }
1069
+ else {
1070
+ self._previewBuildQueue.delete(preview);
1071
+ }
1072
+ }
1073
+
1074
+ this._scheduleIdle(buildChunk);
1075
+ };
1076
+
1042
1077
  SourceGroup.prototype._createImagePreview = function(preview, image, redraw) {
1043
1078
  preview.imageData = {
1044
1079
  image: image,
@@ -1059,27 +1094,19 @@ define([
1059
1094
  preview.imageData.width = preview.imageData.height * preview.imageData.dimRatio;
1060
1095
  preview.imageData.imageSpacing = preview.imageData.width * SPACING_BETWEEN_PREVIEWS;
1061
1096
 
1062
- var currentX = preview.imageData.borderSpacing;
1097
+ this._addToUnwrap(preview.group);
1063
1098
 
1064
- while (currentX < this._width) {
1065
- var imagePreview = new Konva.Image({
1066
- x: currentX,
1067
- y: preview.imageData.borderSpacing,
1068
- image: image,
1069
- width: preview.imageData.width,
1070
- height: preview.imageData.height,
1071
- listening: false
1072
- });
1099
+ var interImageSpacing = preview.imageData.width + preview.imageData.imageSpacing;
1073
1100
 
1074
- preview.group.add(imagePreview);
1101
+ var targetCount = 0;
1075
1102
 
1076
- currentX += preview.imageData.width + preview.imageData.imageSpacing;
1103
+ if (this._width > preview.imageData.borderSpacing) {
1104
+ targetCount = Math.trunc((this._width - preview.imageData.borderSpacing) / interImageSpacing) + 1;
1077
1105
  }
1078
-
1079
- this._addToUnwrap(preview.group);
1106
+ this._ensureImagePreviewCount(preview, targetCount, interImageSpacing);
1080
1107
 
1081
1108
  if (redraw) {
1082
- this._group.draw();
1109
+ this._batchDraw();
1083
1110
  }
1084
1111
 
1085
1112
  this._previewList.push(preview);
@@ -1652,7 +1679,7 @@ define([
1652
1679
  self._source.volume = Math.max(self._source.volumeRange[0], Math.min(volume, self._source.volumeRange[1]));
1653
1680
  self._peaks.emit('source.volumeChanged', self._source);
1654
1681
 
1655
- self._group.draw();
1682
+ self._batchDraw();
1656
1683
  });
1657
1684
 
1658
1685
  volumeSliderGroup.on('dragend', function() {
@@ -160,7 +160,7 @@ define([
160
160
  }
161
161
  }.bind(this));
162
162
 
163
- this.draw();
163
+ this.batchDraw();
164
164
  };
165
165
 
166
166
  SourcesLayer.prototype._onSourcesAdd = function(sources) {
@@ -190,7 +190,7 @@ define([
190
190
 
191
191
  this._view.updateTimelineLength();
192
192
 
193
- this._layer.draw();
193
+ this._layer.batchDraw();
194
194
  };
195
195
 
196
196
  SourcesLayer.prototype._onSourcesShow = function(sources) {
@@ -200,7 +200,7 @@ define([
200
200
  self._sourcesGroup[source.id].setWrapping(false, true);
201
201
  });
202
202
 
203
- this._layer.draw();
203
+ this._layer.batchDraw();
204
204
  };
205
205
 
206
206
  SourcesLayer.prototype._onSourcesHide = function(sources) {
@@ -210,7 +210,7 @@ define([
210
210
  self._sourcesGroup[source.id].setWrapping(true, true);
211
211
  });
212
212
 
213
- this._layer.draw();
213
+ this._layer.batchDraw();
214
214
  };
215
215
 
216
216
  SourcesLayer.prototype._onDataRetrieved = function(data, source, url) {
@@ -243,7 +243,7 @@ define([
243
243
  SourcesLayer.prototype._onSegmentsShow = function(segmentsGroupId, lineId) {
244
244
  this._lineGroups.addSegments(segmentsGroupId, lineId);
245
245
  this._view.updateTimelineLength();
246
- this._layer.draw();
246
+ this._layer.batchDraw();
247
247
  };
248
248
 
249
249
  /**
@@ -285,7 +285,7 @@ define([
285
285
 
286
286
  if (sourceGroup) {
287
287
  sourceGroup.createIndicators();
288
- this._layer.draw();
288
+ this._layer.batchDraw();
289
289
  }
290
290
  };
291
291
 
@@ -312,7 +312,7 @@ define([
312
312
  count += this._removeInvisibleSources(startTime, endTime);
313
313
 
314
314
  if (count > 0) {
315
- this._layer.draw();
315
+ this._layer.batchDraw();
316
316
  }
317
317
  };
318
318
 
@@ -365,7 +365,7 @@ define([
365
365
 
366
366
  this._draggedElementId = null;
367
367
 
368
- this._view.drawSourcesLayer();
368
+ this._view.batchDrawSourcesLayer();
369
369
  this._view.updateTimelineLength();
370
370
 
371
371
  this._peaks.emit('sources.updated', updatedSources);
@@ -409,7 +409,7 @@ define([
409
409
  );
410
410
 
411
411
  if (shouldRedraw) {
412
- this.draw();
412
+ this.batchDraw();
413
413
  }
414
414
  };
415
415
 
@@ -625,8 +625,8 @@ define([
625
625
  this._layer.setVisible(visible);
626
626
  };
627
627
 
628
- SourcesLayer.prototype.draw = function() {
629
- this._layer.draw();
628
+ SourcesLayer.prototype.batchDraw = function() {
629
+ this._layer.batchDraw();
630
630
  };
631
631
 
632
632
  SourcesLayer.prototype.listening = function(bool) {
@@ -682,7 +682,7 @@ define([
682
682
  });
683
683
  }
684
684
  }
685
- this._layer.draw();
685
+ this._layer.batchDraw();
686
686
  };
687
687
 
688
688
  SourcesLayer.prototype._shouldResampleAudio = function(audioUrl, urls) {