@checksub_team/peaks_timeline 1.4.45 → 1.4.47

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checksub_team/peaks_timeline",
3
- "version": "1.4.45",
3
+ "version": "1.4.47",
4
4
  "description": "JavaScript UI component for displaying audio waveforms",
5
5
  "main": "./peaks.js",
6
6
  "types": "./peaks.js.d.ts",
package/peaks.js CHANGED
@@ -16371,9 +16371,13 @@ module.exports = function (Konva) {
16371
16371
  return SegmentMarker;
16372
16372
  }(_dereq_('konva'));
16373
16373
  },{"konva":43}],101:[function(_dereq_,module,exports){
16374
- module.exports = function (Konva, SegmentMarker) {
16374
+ module.exports = function (Konva, SegmentMarker, Utils) {
16375
16375
  'use strict';
16376
16376
  var SEGMENT_WIDTH = 10;
16377
+ var SEGMENT_CORNER_RADIUS = 10;
16378
+ var INDICATOR_RADIUS = 4;
16379
+ var INDICATORS_MARGIN_RIGHT = 4;
16380
+ var INDICATORS_MARGIN_TOP = 8;
16377
16381
  function SegmentShape(segment, peaks, group, view) {
16378
16382
  this._segment = segment;
16379
16383
  this._peaks = peaks;
@@ -16383,22 +16387,33 @@ module.exports = function (Konva, SegmentMarker) {
16383
16387
  this._label = null;
16384
16388
  this._startMarker = null;
16385
16389
  this._endMarker = null;
16390
+ this._shapeGroup = null;
16386
16391
  this._rectangle = null;
16387
16392
  this._isSelected = false;
16393
+ this._indicators = {};
16394
+ var self = this;
16395
+ this._segmentWidth = this._view.timeToPixels(this._segment.endTime - this._segment.startTime);
16388
16396
  this._segmentHeight = this._peaks.options.segmentHeight;
16389
- this._rectangle = new Konva.Rect({
16397
+ this._shapeGroup = new Konva.Group({
16390
16398
  x: this._view.timeToPixels(this._segment.startTime),
16391
16399
  y: 0,
16400
+ width: this._segmentWidth,
16401
+ height: this._segmentHeight,
16402
+ draggable: this._segment.editable,
16403
+ clipFunc: function (ctx) {
16404
+ self._drawRect(ctx);
16405
+ }
16406
+ });
16407
+ this._rectangle = new Konva.Rect({
16392
16408
  width: this._view.timeToPixels(this._segment.endTime - this._segment.startTime),
16393
16409
  height: this._segmentHeight,
16394
- cornerRadius: 10,
16410
+ cornerRadius: SEGMENT_CORNER_RADIUS,
16395
16411
  fill: segment.color + Math.round(segment.opacity * 255).toString(16),
16396
16412
  stroke: segment.textColor + 'FF',
16397
- strokeWidth: 1,
16398
- draggable: this._segment.editable
16413
+ strokeWidth: 2
16399
16414
  });
16400
- var self = this;
16401
- this._rectangle.dragBoundFunc(function () {
16415
+ this._shapeGroup.add(this._rectangle);
16416
+ this._shapeGroup.dragBoundFunc(function () {
16402
16417
  var diff = self._view.getPointerPosition().x - self._mouseDownX;
16403
16418
  self._group.updateSegment(self._segment, self._initialStartPixel + diff, self._initialEndPixel + diff);
16404
16419
  self._startMarker.timeUpdated(self._segment.startTime);
@@ -16408,11 +16423,11 @@ module.exports = function (Konva, SegmentMarker) {
16408
16423
  y: this.absolutePosition().y
16409
16424
  };
16410
16425
  });
16411
- this._rectangle.on('mouseenter', this._onMouseEnter.bind(this));
16412
- this._rectangle.on('mouseleave', this._onMouseLeave.bind(this));
16413
- this._rectangle.on('click', this._onClick.bind(this));
16414
- this._rectangle.on('dragstart', this._onSegmentDragStart.bind(this));
16415
- this._rectangle.on('dragend', this._onSegmentDragEnd.bind(this));
16426
+ this._shapeGroup.on('mouseenter', this._onMouseEnter.bind(this));
16427
+ this._shapeGroup.on('mouseleave', this._onMouseLeave.bind(this));
16428
+ this._shapeGroup.on('click', this._onClick.bind(this));
16429
+ this._shapeGroup.on('dragstart', this._onSegmentDragStart.bind(this));
16430
+ this._shapeGroup.on('dragend', this._onSegmentDragEnd.bind(this));
16416
16431
  this._onSegmentHandleDrag = this._onSegmentHandleDrag.bind(this);
16417
16432
  this._onSegmentHandleDragStart = this._onSegmentHandleDragStart.bind(this);
16418
16433
  this._onSegmentHandleDragEnd = this._onSegmentHandleDragEnd.bind(this);
@@ -16427,15 +16442,21 @@ module.exports = function (Konva, SegmentMarker) {
16427
16442
  fontSize: 12
16428
16443
  });
16429
16444
  this._createMarkers();
16445
+ this._indicatorsGroup = new Konva.Group();
16446
+ this._shapeGroup.add(this._indicatorsGroup);
16447
+ this.createIndicators();
16430
16448
  }
16431
16449
  SegmentShape.prototype.update = function () {
16432
16450
  var startPixel = this._view.timeToPixels(this._segment.startTime);
16433
16451
  var endPixel = this._view.timeToPixels(this._segment.endTime);
16434
16452
  var frameOffset = this._view.timeToPixels(this._view.getTimeOffset());
16435
- this._rectangle.x(startPixel - frameOffset);
16436
- this._rectangle.width(endPixel - startPixel);
16437
- var newWidth = Math.floor(this._rectangle.width() / 2);
16438
- if (this._rectangle.width() < this._startMarker.getHandleWidth() + this._endMarker.getHandleWidth()) {
16453
+ this._shapeGroup.x(startPixel - frameOffset);
16454
+ this._segmentWidth = endPixel - startPixel;
16455
+ this._shapeGroup.width(this._segmentWidth);
16456
+ this._rectangle.width(this._segmentWidth);
16457
+ this._indicatorsGroup.x(this._segmentWidth);
16458
+ var newWidth = Math.floor(this._segmentWidth / 2);
16459
+ if (this._segmentWidth < this._startMarker.getHandleWidth() + this._endMarker.getHandleWidth()) {
16439
16460
  this._startMarker.setHandleWidth(newWidth);
16440
16461
  this._endMarker.setHandleWidth(newWidth);
16441
16462
  } else if (this._startMarker.getHandleWidth() < SEGMENT_WIDTH && newWidth > this._startMarker.getHandleWidth()) {
@@ -16477,7 +16498,7 @@ module.exports = function (Konva, SegmentMarker) {
16477
16498
  if (segmentsGroup) {
16478
16499
  this._segmentsGroup = segmentsGroup;
16479
16500
  }
16480
- group.add(this._rectangle);
16501
+ group.add(this._shapeGroup);
16481
16502
  if (this._label) {
16482
16503
  group.add(this._label);
16483
16504
  }
@@ -16541,6 +16562,54 @@ module.exports = function (Konva, SegmentMarker) {
16541
16562
  });
16542
16563
  }
16543
16564
  };
16565
+ SegmentShape.prototype.createIndicators = function () {
16566
+ var newIndicatorsColors = this._segment.indicators;
16567
+ var oldIndicators = this._indicators;
16568
+ var newIndicators = {};
16569
+ if (newIndicatorsColors) {
16570
+ newIndicatorsColors.forEach(function (indicatorColor) {
16571
+ var oldIndicator = oldIndicators[indicatorColor];
16572
+ if (oldIndicator) {
16573
+ newIndicators[indicatorColor] = oldIndicator;
16574
+ delete oldIndicators[indicatorColor];
16575
+ } else {
16576
+ newIndicators[indicatorColor] = null;
16577
+ }
16578
+ });
16579
+ for (var color in oldIndicators) {
16580
+ if (Utils.objectHasProperty(oldIndicators, color)) {
16581
+ oldIndicators[color].destroy();
16582
+ }
16583
+ }
16584
+ }
16585
+ this._indicators = Object.keys(newIndicators).sort().reverse().reduce(function (objEntries, key) {
16586
+ objEntries[key] = newIndicators[key];
16587
+ return objEntries;
16588
+ }, {});
16589
+ this._createIndicators();
16590
+ };
16591
+ SegmentShape.prototype._createIndicators = function () {
16592
+ var currentX = 0;
16593
+ var zIndex = 0;
16594
+ for (var color in this._indicators) {
16595
+ if (Utils.objectHasProperty(this._indicators, color)) {
16596
+ if (!this._indicators[color]) {
16597
+ this._indicators[color] = new Konva.Circle({
16598
+ radius: INDICATOR_RADIUS,
16599
+ fill: color,
16600
+ strokeEnabled: false
16601
+ });
16602
+ this._indicatorsGroup.add(this._indicators[color]);
16603
+ }
16604
+ this._indicators[color].x(currentX);
16605
+ this._indicators[color].zIndex(zIndex);
16606
+ currentX += INDICATOR_RADIUS;
16607
+ zIndex += 1;
16608
+ }
16609
+ }
16610
+ this._indicatorsGroup.offsetX(currentX + INDICATORS_MARGIN_RIGHT);
16611
+ this._indicatorsGroup.offsetY(-INDICATORS_MARGIN_TOP);
16612
+ };
16544
16613
  SegmentShape.prototype._onMouseEnter = function () {
16545
16614
  this._view.setCursor('pointer');
16546
16615
  this._view.setHoveredElement(this);
@@ -16594,7 +16663,7 @@ module.exports = function (Konva, SegmentMarker) {
16594
16663
  }
16595
16664
  };
16596
16665
  SegmentShape.prototype.destroy = function () {
16597
- this._rectangle.destroy();
16666
+ this._shapeGroup.destroy();
16598
16667
  if (this._label) {
16599
16668
  this._label.destroy();
16600
16669
  }
@@ -16605,9 +16674,22 @@ module.exports = function (Konva, SegmentMarker) {
16605
16674
  this._endMarker.destroy();
16606
16675
  }
16607
16676
  };
16677
+ SegmentShape.prototype._drawRect = function (ctx) {
16678
+ ctx.beginPath();
16679
+ ctx.moveTo(SEGMENT_CORNER_RADIUS + 1.5, 0);
16680
+ ctx.lineTo(this._segmentWidth - SEGMENT_CORNER_RADIUS - 1.5, 0);
16681
+ ctx.quadraticCurveTo(this._segmentWidth, 0, this._segmentWidth, SEGMENT_CORNER_RADIUS + 1.5);
16682
+ ctx.lineTo(this._segmentWidth, this._segmentHeight - SEGMENT_CORNER_RADIUS - 1.5);
16683
+ ctx.quadraticCurveTo(this._segmentWidth, this._segmentHeight, this._segmentWidth - SEGMENT_CORNER_RADIUS - 1.5, this._segmentHeight);
16684
+ ctx.lineTo(SEGMENT_CORNER_RADIUS + 1.5, this._segmentHeight);
16685
+ ctx.quadraticCurveTo(0, this._segmentHeight, 0, this._segmentHeight - SEGMENT_CORNER_RADIUS - 1.5);
16686
+ ctx.lineTo(0, SEGMENT_CORNER_RADIUS + 1.5);
16687
+ ctx.quadraticCurveTo(0, 0, SEGMENT_CORNER_RADIUS + 1.5, 0);
16688
+ ctx.closePath();
16689
+ };
16608
16690
  return SegmentShape;
16609
- }(_dereq_('konva'), _dereq_('./segment-marker'));
16610
- },{"./segment-marker":100,"konva":43}],102:[function(_dereq_,module,exports){
16691
+ }(_dereq_('konva'), _dereq_('./segment-marker'), _dereq_('./utils'));
16692
+ },{"./segment-marker":100,"./utils":111,"konva":43}],102:[function(_dereq_,module,exports){
16611
16693
  module.exports = function (Utils) {
16612
16694
  'use strict';
16613
16695
  function validateSegment(peaks, options, context) {
@@ -16615,7 +16697,7 @@ module.exports = function (Utils) {
16615
16697
  throw new TypeError('peaks.segments.' + context + ': startTime should be a valid number');
16616
16698
  }
16617
16699
  if (!Utils.isValidTime(options.endTime)) {
16618
- throw new TypeError('peaks.segments.' + context + ': endTime should be a valid number');
16700
+ options.endTime = options.startTime;
16619
16701
  }
16620
16702
  options.startTime = Utils.roundTime(options.startTime);
16621
16703
  options.endTime = Utils.roundTime(options.endTime);
@@ -16651,7 +16733,7 @@ module.exports = function (Utils) {
16651
16733
  throw new TypeError('peaks.segments.' + context + ': hoverColor must be a boolean');
16652
16734
  }
16653
16735
  }
16654
- function Segment(peaks, id, startTime, endTime, labelText, color, textColor, handleTextColor, hoverColor, opacity, editable, allowDeletion, line) {
16736
+ function Segment(peaks, id, startTime, endTime, labelText, color, textColor, handleTextColor, hoverColor, opacity, editable, allowDeletion, line, indicators) {
16655
16737
  var opts = {
16656
16738
  startTime: startTime,
16657
16739
  endTime: endTime,
@@ -16663,7 +16745,8 @@ module.exports = function (Utils) {
16663
16745
  opacity: opacity,
16664
16746
  editable: editable,
16665
16747
  allowDeletion: allowDeletion,
16666
- line: line
16748
+ line: line,
16749
+ indicators: indicators
16667
16750
  };
16668
16751
  validateSegment(peaks, opts, 'add()');
16669
16752
  this._peaks = peaks;
@@ -16679,6 +16762,7 @@ module.exports = function (Utils) {
16679
16762
  this._editable = opts.editable;
16680
16763
  this._allowDeletion = opts.allowDeletion;
16681
16764
  this._line = opts.line;
16765
+ this._indicators = opts.indicators;
16682
16766
  this._minSize = peaks.options.minSegmentSize;
16683
16767
  }
16684
16768
  Object.defineProperties(Segment.prototype, {
@@ -16760,6 +16844,12 @@ module.exports = function (Utils) {
16760
16844
  return this._line;
16761
16845
  }
16762
16846
  },
16847
+ indicators: {
16848
+ enumerable: true,
16849
+ get: function () {
16850
+ return this._indicators;
16851
+ }
16852
+ },
16763
16853
  minSize: {
16764
16854
  enumerable: true,
16765
16855
  get: function () {
@@ -16779,7 +16869,8 @@ module.exports = function (Utils) {
16779
16869
  opacity: this.opacity,
16780
16870
  editable: this.editable,
16781
16871
  allowDeletion: this.allowDeletion,
16782
- line: this.line
16872
+ line: this.line,
16873
+ indicators: this.indicators
16783
16874
  };
16784
16875
  Utils.extend(opts, options);
16785
16876
  validateSegment(this._peaks, opts, 'update()');
@@ -16794,11 +16885,16 @@ module.exports = function (Utils) {
16794
16885
  this._editable = opts.editable;
16795
16886
  this._allowDeletion = opts.allowDeletion;
16796
16887
  this._line = opts.line;
16888
+ this._indicators = opts.indicators;
16797
16889
  this._peaks.emit('segment.updated', this);
16798
16890
  };
16799
16891
  Segment.prototype.isVisible = function (startTime, endTime) {
16800
16892
  return this.startTime < endTime && startTime < this.endTime;
16801
16893
  };
16894
+ Segment.prototype.setIndicators = function (newIndicators) {
16895
+ this._indicators = newIndicators;
16896
+ this._peaks.emit('segment.setIndicators', this);
16897
+ };
16802
16898
  return Segment;
16803
16899
  }(_dereq_('./utils'));
16804
16900
  },{"./utils":111}],103:[function(_dereq_,module,exports){
@@ -16816,6 +16912,7 @@ module.exports = function (SegmentShape, Utils, Konva) {
16816
16912
  this._updatedSegments = [];
16817
16913
  this._isMagnetized = false;
16818
16914
  this._peaks.on('segments.setMagnetizing', this.setMagnetizing.bind(this));
16915
+ this._peaks.on('segment.setIndicators', this.setIndicators.bind(this));
16819
16916
  }
16820
16917
  SegmentsGroup.prototype.addToGroup = function (group) {
16821
16918
  group.add(this._group);
@@ -17084,6 +17181,13 @@ module.exports = function (SegmentShape, Utils, Konva) {
17084
17181
  SegmentsGroup.prototype.isMagnetized = function () {
17085
17182
  return this._isMagnetized;
17086
17183
  };
17184
+ SegmentsGroup.prototype.setIndicators = function (segment) {
17185
+ var segmentShape = this._segmentShapes[segment.id];
17186
+ if (segmentShape) {
17187
+ segmentShape.createIndicators();
17188
+ this._draw();
17189
+ }
17190
+ };
17087
17191
  SegmentsGroup.prototype.addToUpdatedSegments = function (segment) {
17088
17192
  if (this._updatedSegments.indexOf(segment) === -1) {
17089
17193
  this._updatedSegments.push(segment);
@@ -18895,6 +18999,7 @@ module.exports = function (Utils, Konva) {
18895
18999
  'use strict';
18896
19000
  var LEFT_PADDING = 4;
18897
19001
  function TimelineAxis(peaks, view, options) {
19002
+ this._view = view;
18898
19003
  var self = this;
18899
19004
  peaks.on('playhead.moved', this._onPlayheadMoved.bind(this));
18900
19005
  peaks.on('playhead.hidden', this._onPlayheadHidden.bind(this));
@@ -18916,8 +19021,8 @@ module.exports = function (Utils, Konva) {
18916
19021
  self._frontLayer.add(self._timesShape);
18917
19022
  }
18918
19023
  TimelineAxis.prototype._onPlayheadMoved = function (playheadX, playheadWidth) {
18919
- this._maskStart = playheadX;
18920
- this._maskEnd = playheadX + playheadWidth;
19024
+ this._maskStart = playheadX + this._view.getFrameOffset();
19025
+ this._maskEnd = playheadX + this._view.getFrameOffset() + playheadWidth;
18921
19026
  this._frontLayer.draw();
18922
19027
  };
18923
19028
  TimelineAxis.prototype._onPlayheadHidden = function () {
@@ -19015,7 +19120,7 @@ module.exports = function (Utils, Konva) {
19015
19120
  var labelWidth = context.measureText(label).width;
19016
19121
  var labelX = x + LEFT_PADDING;
19017
19122
  var labelY = labelHeight;
19018
- if (!this._labelIsMasked(labelX, labelX + labelWidth)) {
19123
+ if (!this._labelIsMasked(labelX + view.getFrameOffset(), labelX + view.getFrameOffset() + labelWidth)) {
19019
19124
  context.fillText(label, labelX, labelY);
19020
19125
  }
19021
19126
  secs += axisLabelIntervalSecs;
@@ -19074,7 +19179,7 @@ module.exports = function (Colors, Segment, Utils) {
19074
19179
  if (!Utils.isObject(options)) {
19075
19180
  throw new TypeError('peaks.segments.add(): expected a Segment object parameter');
19076
19181
  }
19077
- var segment = new Segment(this._peaks, Utils.isNullOrUndefined(options.id) ? this._getNextSegmentId() : options.id, options.startTime, options.endTime, options.labelText, options.color || this._getSegmentColor(), options.textColor || '#000000', options.handleTextColor || '#000000', options.hoverColor, options.opacity || 1, options.editable, options.allowDeletion || false, options.line);
19182
+ var segment = new Segment(this._peaks, Utils.isNullOrUndefined(options.id) ? this._getNextSegmentId() : options.id, options.startTime, options.endTime, options.labelText, options.color || this._getSegmentColor(), options.textColor || '#000000', options.handleTextColor || '#000000', options.hoverColor, options.opacity || 1, options.editable, options.allowDeletion || false, options.line, options.indicators);
19078
19183
  return segment;
19079
19184
  };
19080
19185
  TimelineSegments.prototype.getSegments = function () {
@@ -8,13 +8,19 @@
8
8
 
9
9
  define([
10
10
  'konva',
11
- './segment-marker'
11
+ './segment-marker',
12
+ './utils'
12
13
  ], function(
13
14
  Konva,
14
- SegmentMarker) {
15
+ SegmentMarker,
16
+ Utils) {
15
17
  'use strict';
16
18
 
17
19
  var SEGMENT_WIDTH = 10;
20
+ var SEGMENT_CORNER_RADIUS = 10;
21
+ var INDICATOR_RADIUS = 4; // px
22
+ var INDICATORS_MARGIN_RIGHT = 4; // px
23
+ var INDICATORS_MARGIN_TOP = 8; // px
18
24
 
19
25
  /**
20
26
  * Creates a waveform segment shape with optional start and end markers.
@@ -38,26 +44,39 @@ define([
38
44
  this._label = null;
39
45
  this._startMarker = null;
40
46
  this._endMarker = null;
47
+ this._shapeGroup = null;
41
48
  this._rectangle = null;
42
49
  this._isSelected = false;
50
+ this._indicators = {};
43
51
 
52
+ var self = this;
53
+
54
+ this._segmentWidth = this._view.timeToPixels(this._segment.endTime - this._segment.startTime);
44
55
  this._segmentHeight = this._peaks.options.segmentHeight;
45
56
 
46
- this._rectangle = new Konva.Rect({
57
+ this._shapeGroup = new Konva.Group({
47
58
  x: this._view.timeToPixels(this._segment.startTime),
48
59
  y: 0,
60
+ width: this._segmentWidth,
61
+ height: this._segmentHeight,
62
+ draggable: this._segment.editable,
63
+ clipFunc: function(ctx) {
64
+ self._drawRect(ctx);
65
+ }
66
+ });
67
+
68
+ this._rectangle = new Konva.Rect({
49
69
  width: this._view.timeToPixels(this._segment.endTime - this._segment.startTime),
50
70
  height: this._segmentHeight,
51
- cornerRadius: 10,
71
+ cornerRadius: SEGMENT_CORNER_RADIUS,
52
72
  fill: segment.color + Math.round(segment.opacity * 255).toString(16),
53
73
  stroke: segment.textColor + 'FF',
54
- strokeWidth: 1,
55
- draggable: this._segment.editable
74
+ strokeWidth: 2
56
75
  });
57
76
 
58
- var self = this;
77
+ this._shapeGroup.add(this._rectangle);
59
78
 
60
- this._rectangle.dragBoundFunc(function() {
79
+ this._shapeGroup.dragBoundFunc(function() {
61
80
  var diff = self._view.getPointerPosition().x - self._mouseDownX;
62
81
 
63
82
  self._group.updateSegment(
@@ -76,12 +95,12 @@ define([
76
95
 
77
96
  // Set up event handlers to show/hide the segment label text when the user
78
97
  // hovers the mouse over the segment.
79
- this._rectangle.on('mouseenter', this._onMouseEnter.bind(this));
80
- this._rectangle.on('mouseleave', this._onMouseLeave.bind(this));
81
- this._rectangle.on('click', this._onClick.bind(this));
98
+ this._shapeGroup.on('mouseenter', this._onMouseEnter.bind(this));
99
+ this._shapeGroup.on('mouseleave', this._onMouseLeave.bind(this));
100
+ this._shapeGroup.on('click', this._onClick.bind(this));
82
101
 
83
- this._rectangle.on('dragstart', this._onSegmentDragStart.bind(this));
84
- this._rectangle.on('dragend', this._onSegmentDragEnd.bind(this));
102
+ this._shapeGroup.on('dragstart', this._onSegmentDragStart.bind(this));
103
+ this._shapeGroup.on('dragend', this._onSegmentDragEnd.bind(this));
85
104
 
86
105
  // Event handlers for markers
87
106
  this._onSegmentHandleDrag = this._onSegmentHandleDrag.bind(this);
@@ -100,6 +119,11 @@ define([
100
119
  });
101
120
 
102
121
  this._createMarkers();
122
+
123
+ this._indicatorsGroup = new Konva.Group();
124
+ this._shapeGroup.add(this._indicatorsGroup);
125
+
126
+ this.createIndicators();
103
127
  }
104
128
 
105
129
  SegmentShape.prototype.update = function() {
@@ -107,13 +131,17 @@ define([
107
131
  var endPixel = this._view.timeToPixels(this._segment.endTime);
108
132
  var frameOffset = this._view.timeToPixels(this._view.getTimeOffset());
109
133
 
110
- this._rectangle.x(startPixel - frameOffset);
134
+ this._shapeGroup.x(startPixel - frameOffset);
111
135
 
112
- this._rectangle.width(endPixel - startPixel);
136
+ this._segmentWidth = endPixel - startPixel;
113
137
 
114
- var newWidth = Math.floor(this._rectangle.width() / 2);
138
+ this._shapeGroup.width(this._segmentWidth);
139
+ this._rectangle.width(this._segmentWidth);
140
+ this._indicatorsGroup.x(this._segmentWidth);
115
141
 
116
- if (this._rectangle.width()
142
+ var newWidth = Math.floor(this._segmentWidth / 2);
143
+
144
+ if (this._segmentWidth
117
145
  < this._startMarker.getHandleWidth() + this._endMarker.getHandleWidth()) {
118
146
  this._startMarker.setHandleWidth(newWidth);
119
147
  this._endMarker.setHandleWidth(newWidth);
@@ -169,7 +197,7 @@ define([
169
197
  this._segmentsGroup = segmentsGroup;
170
198
  }
171
199
 
172
- group.add(this._rectangle);
200
+ group.add(this._shapeGroup);
173
201
 
174
202
  if (this._label) {
175
203
  group.add(this._label);
@@ -242,6 +270,69 @@ define([
242
270
  }
243
271
  };
244
272
 
273
+ SegmentShape.prototype.createIndicators = function() {
274
+ var newIndicatorsColors = this._segment.indicators;
275
+ var oldIndicators = this._indicators;
276
+ var newIndicators = {};
277
+
278
+ if (newIndicatorsColors) {
279
+ newIndicatorsColors.forEach(function(indicatorColor) {
280
+ var oldIndicator = oldIndicators[indicatorColor];
281
+
282
+ if (oldIndicator) {
283
+ newIndicators[indicatorColor] = oldIndicator;
284
+ delete oldIndicators[indicatorColor];
285
+ }
286
+ else {
287
+ newIndicators[indicatorColor] = null;
288
+ }
289
+ });
290
+
291
+ for (var color in oldIndicators) {
292
+ if (Utils.objectHasProperty(oldIndicators, color)) {
293
+ oldIndicators[color].destroy();
294
+ }
295
+ }
296
+ }
297
+
298
+ this._indicators = Object.keys(newIndicators)
299
+ .sort()
300
+ .reverse()
301
+ .reduce(function(objEntries, key) {
302
+ objEntries[key] = newIndicators[key];
303
+ return objEntries;
304
+ }, {}
305
+ );
306
+
307
+ this._createIndicators();
308
+ };
309
+
310
+ SegmentShape.prototype._createIndicators = function() {
311
+ var currentX = 0;
312
+ var zIndex = 0;
313
+
314
+ for (var color in this._indicators) {
315
+ if (Utils.objectHasProperty(this._indicators, color)) {
316
+ if (!this._indicators[color]) {
317
+ this._indicators[color] = new Konva.Circle({
318
+ radius: INDICATOR_RADIUS,
319
+ fill: color,
320
+ strokeEnabled: false
321
+ });
322
+ this._indicatorsGroup.add(this._indicators[color]);
323
+ }
324
+
325
+ this._indicators[color].x(currentX);
326
+ this._indicators[color].zIndex(zIndex);
327
+ currentX += INDICATOR_RADIUS;
328
+ zIndex += 1;
329
+ }
330
+ }
331
+
332
+ this._indicatorsGroup.offsetX(currentX + INDICATORS_MARGIN_RIGHT);
333
+ this._indicatorsGroup.offsetY(-INDICATORS_MARGIN_TOP);
334
+ };
335
+
245
336
  SegmentShape.prototype._onMouseEnter = function() {
246
337
  this._view.setCursor('pointer');
247
338
 
@@ -335,7 +426,7 @@ define([
335
426
  };
336
427
 
337
428
  SegmentShape.prototype.destroy = function() {
338
- this._rectangle.destroy();
429
+ this._shapeGroup.destroy();
339
430
 
340
431
  if (this._label) {
341
432
  this._label.destroy();
@@ -350,5 +441,26 @@ define([
350
441
  }
351
442
  };
352
443
 
444
+ SegmentShape.prototype._drawRect = function(ctx) {
445
+ ctx.beginPath();
446
+ ctx.moveTo(SEGMENT_CORNER_RADIUS + 1.5, 0);
447
+ ctx.lineTo(this._segmentWidth - SEGMENT_CORNER_RADIUS - 1.5, 0);
448
+ ctx.quadraticCurveTo(this._segmentWidth, 0, this._segmentWidth, SEGMENT_CORNER_RADIUS + 1.5);
449
+ ctx.lineTo(this._segmentWidth, this._segmentHeight - SEGMENT_CORNER_RADIUS - 1.5);
450
+ ctx.quadraticCurveTo(
451
+ this._segmentWidth,
452
+ this._segmentHeight,
453
+ this._segmentWidth - SEGMENT_CORNER_RADIUS - 1.5,
454
+ this._segmentHeight
455
+ );
456
+ ctx.lineTo(SEGMENT_CORNER_RADIUS + 1.5, this._segmentHeight);
457
+ ctx.quadraticCurveTo(
458
+ 0, this._segmentHeight, 0, this._segmentHeight - SEGMENT_CORNER_RADIUS - 1.5
459
+ );
460
+ ctx.lineTo(0, SEGMENT_CORNER_RADIUS + 1.5);
461
+ ctx.quadraticCurveTo(0, 0, SEGMENT_CORNER_RADIUS + 1.5, 0);
462
+ ctx.closePath();
463
+ };
464
+
353
465
  return SegmentShape;
354
466
  });
package/src/segment.js CHANGED
@@ -13,13 +13,11 @@ define([
13
13
 
14
14
  function validateSegment(peaks, options, context) {
15
15
  if (!Utils.isValidTime(options.startTime)) {
16
- // eslint-disable-next-line max-len
17
16
  throw new TypeError('peaks.segments.' + context + ': startTime should be a valid number');
18
17
  }
19
18
 
20
19
  if (!Utils.isValidTime(options.endTime)) {
21
- // eslint-disable-next-line max-len
22
- throw new TypeError('peaks.segments.' + context + ': endTime should be a valid number');
20
+ options.endTime = options.startTime;
23
21
  }
24
22
 
25
23
  options.startTime = Utils.roundTime(options.startTime);
@@ -39,12 +37,10 @@ define([
39
37
  options.endTime = Utils.roundTime(options.endTime);
40
38
 
41
39
  if (options.opacity < 0 || options.opacity > 1) {
42
- // eslint-disable-next-line max-len
43
40
  throw new RangeError('peaks.segments.' + context + ': opacity should be between 0 and 1');
44
41
  }
45
42
 
46
43
  if (Utils.isNullOrUndefined(options.labelText)) {
47
- // Set default label text
48
44
  options.labelText = '';
49
45
  }
50
46
  else if (!Utils.isString(options.labelText)) {
@@ -85,11 +81,16 @@ define([
85
81
  * @param {Number} opacity Segment waveform opacity.
86
82
  * @param {Boolean} editable If <code>true</code> the segment start and
87
83
  * end times can be adjusted via the user interface.
84
+ * @param {Boolean} allowDeletion If <code>true</code> the segment can be
85
+ * deleted using the delete key.
86
+ * @param {Number} line The id of the line to add the segment to.
87
+ * @param {Array<String>} indicators Array containing the colors
88
+ * of all indicators.
88
89
  */
89
90
 
90
91
  function Segment(peaks, id, startTime, endTime, labelText, color,
91
92
  textColor, handleTextColor, hoverColor, opacity, editable,
92
- allowDeletion, line) {
93
+ allowDeletion, line, indicators) {
93
94
  var opts = {
94
95
  startTime: startTime,
95
96
  endTime: endTime,
@@ -101,7 +102,8 @@ define([
101
102
  opacity: opacity,
102
103
  editable: editable,
103
104
  allowDeletion: allowDeletion,
104
- line: line
105
+ line: line,
106
+ indicators: indicators
105
107
  };
106
108
 
107
109
  validateSegment(peaks, opts, 'add()');
@@ -119,6 +121,7 @@ define([
119
121
  this._editable = opts.editable;
120
122
  this._allowDeletion = opts.allowDeletion;
121
123
  this._line = opts.line;
124
+ this._indicators = opts.indicators;
122
125
  this._minSize = peaks.options.minSegmentSize;
123
126
  }
124
127
 
@@ -203,6 +206,12 @@ define([
203
206
  return this._line;
204
207
  }
205
208
  },
209
+ indicators: {
210
+ enumerable: true,
211
+ get: function() {
212
+ return this._indicators;
213
+ }
214
+ },
206
215
  minSize: {
207
216
  enumerable: true,
208
217
  get: function() {
@@ -223,7 +232,8 @@ define([
223
232
  opacity: this.opacity,
224
233
  editable: this.editable,
225
234
  allowDeletion: this.allowDeletion,
226
- line: this.line
235
+ line: this.line,
236
+ indicators: this.indicators
227
237
  };
228
238
 
229
239
  Utils.extend(opts, options);
@@ -241,6 +251,7 @@ define([
241
251
  this._editable = opts.editable;
242
252
  this._allowDeletion = opts.allowDeletion;
243
253
  this._line = opts.line;
254
+ this._indicators = opts.indicators;
244
255
 
245
256
  this._peaks.emit('segment.updated', this);
246
257
  };
@@ -259,5 +270,16 @@ define([
259
270
  return this.startTime < endTime && startTime < this.endTime;
260
271
  };
261
272
 
273
+ /**
274
+ * Update the indicators of this segment.
275
+ *
276
+ * @param {Array<String>} newIndicators The new indicators.
277
+ */
278
+
279
+ Segment.prototype.setIndicators = function(newIndicators) {
280
+ this._indicators = newIndicators;
281
+ this._peaks.emit('segment.setIndicators', this);
282
+ };
283
+
262
284
  return Segment;
263
285
  });
@@ -45,6 +45,7 @@ define([
45
45
  this._isMagnetized = false;
46
46
 
47
47
  this._peaks.on('segments.setMagnetizing', this.setMagnetizing.bind(this));
48
+ this._peaks.on('segment.setIndicators', this.setIndicators.bind(this));
48
49
  }
49
50
 
50
51
  /**
@@ -459,6 +460,15 @@ define([
459
460
  return this._isMagnetized;
460
461
  };
461
462
 
463
+ SegmentsGroup.prototype.setIndicators = function(segment) {
464
+ var segmentShape = this._segmentShapes[segment.id];
465
+
466
+ if (segmentShape) {
467
+ segmentShape.createIndicators();
468
+ this._draw();
469
+ }
470
+ };
471
+
462
472
  SegmentsGroup.prototype.addToUpdatedSegments = function(segment) {
463
473
  if (this._updatedSegments.indexOf(segment) === -1) {
464
474
  this._updatedSegments.push(segment);
@@ -27,6 +27,8 @@ define([
27
27
  */
28
28
 
29
29
  function TimelineAxis(peaks, view, options) {
30
+ this._view = view;
31
+
30
32
  var self = this;
31
33
 
32
34
  peaks.on('playhead.moved', this._onPlayheadMoved.bind(this));
@@ -59,8 +61,8 @@ define([
59
61
  }
60
62
 
61
63
  TimelineAxis.prototype._onPlayheadMoved = function(playheadX, playheadWidth) {
62
- this._maskStart = playheadX;
63
- this._maskEnd = playheadX + playheadWidth;
64
+ this._maskStart = playheadX + this._view.getFrameOffset();
65
+ this._maskEnd = playheadX + this._view.getFrameOffset() + playheadWidth;
64
66
  this._frontLayer.draw();
65
67
  };
66
68
 
@@ -217,7 +219,10 @@ define([
217
219
  var labelX = x + LEFT_PADDING;
218
220
  var labelY = labelHeight;
219
221
 
220
- if (!this._labelIsMasked(labelX, labelX + labelWidth)) {
222
+ if (!this._labelIsMasked(
223
+ labelX + view.getFrameOffset(),
224
+ labelX + view.getFrameOffset() + labelWidth
225
+ )) {
221
226
  context.fillText(label, labelX, labelY);
222
227
  }
223
228
 
@@ -139,7 +139,8 @@ define([
139
139
  options.opacity || 1,
140
140
  options.editable,
141
141
  options.allowDeletion || false,
142
- options.line
142
+ options.line,
143
+ options.indicators
143
144
  );
144
145
 
145
146
  return segment;