peaks.js
peaks.js copied to clipboard
Display the segments text labels inside each respective segments, instead of in the top left corner.
Is there a way to customize the segments in order to achieve this? I would like the text labels to be visible at all time, and to be displayed inside of the segments.
I took a look at the Customizing Peak.js section but I can't find info as to how to change the behavior of the labeltext other than not displaying it.
I am very close to making it work, what I did is I created a custom Segment marker with an additional Konva.Text object. Now the only thing that I'm missing is how to get the width of a segment, so that the text doesn't overflow outside of one. Any pointers for that?
Once I am done I will post my code and solution here.
This is an interesting question. The current customization API doesn't give you control over where the segment label is placed. I did a quick experiment:
If you want the label to always be shown, and not show/hide on mouseover, I removed the code in SegmentShape here, here, and here. To do this properly, instead of removing the code we could add an option flag.
Next, I looked at SegmentShape._updateSegment, which is responsible for updating the position of all displayed segments, e.g., after adding or removing a segment or scrolling the waveform view.
I think this can be refactored to move the code that updates the marker positions into SegmentShape:
// in src/segments-layer.js:
SegmentsLayer.prototype._updateSegment = function(segment) {
var segmentShape = this._findOrAddSegmentShape(segment);
segmentShape.updatePosition();
};
// in src/segment-shape.js:
SegmentShape.prototype.updatePosition = function() {
var segmentStartOffset = this._view.timeToPixels(this._segment.startTime);
var segmentEndOffset = this._view.timeToPixels(this._segment.endTime);
var frameStartOffset = this._view.getFrameOffset();
var startPixel = segmentStartOffset - frameStartOffset;
var endPixel = segmentEndOffset - frameStartOffset;
var marker = this.getStartMarker();
if (marker) {
marker.setX(startPixel - marker.getWidth());
}
marker = this.getEndMarker();
if (marker) {
marker.setX(endPixel);
}
};
With this in place, we could now add code to adjust the label position by adding to SegmentShape.updatePosition. As an example, we could do this:
if (this._label) {
var labelX = startPixel > 0 ? startPixel : 0;
this._label.setX(labelX);
}
The functions you need for positioning the label are:
view.getFrameOffset()- the start position of the waveform shown in the view, in pixelsview.timeToPixels()- converts from time in seconds to pixels
The width of the segment can be calculated from the segmentStartOffset and segmentEndOffset variables.
Some other things to think about:
- Is different behaviour is needed between the zoomable and the overview waveform views?
- What should happen if there are multiple segments close together such that the labels would overlap each other?