diff --git a/demo/custom-markers/main.js b/demo/custom-markers/main.js
index 09d33069..b42986f1 100644
--- a/demo/custom-markers/main.js
+++ b/demo/custom-markers/main.js
@@ -332,7 +332,7 @@ Peaks.init(options, function(err, peaksInstance) {
view.setSegmentDragMode(event.target.value);
});
- // Points mouse events
+ // Point events
peaksInstance.on('points.mouseenter', function(event) {
console.log('points.mouseenter:', event);
@@ -368,7 +368,7 @@ Peaks.init(options, function(err, peaksInstance) {
console.log('points.dragend:', event);
});
- // Segments mouse events
+ // Segment events
peaksInstance.on('segments.dragstart', function(event) {
console.log('segments.dragstart:', event);
@@ -404,6 +404,8 @@ Peaks.init(options, function(err, peaksInstance) {
console.log('segments.contextmenu:', event);
});
+ // Zoomview waveform events
+
peaksInstance.on('zoomview.click', function(event) {
console.log('zoomview.click:', event);
});
@@ -418,6 +420,12 @@ Peaks.init(options, function(err, peaksInstance) {
console.log('zoomview.contextmenu:', event);
});
+ peaksInstance.on('zoomview.update', function(event) {
+ console.log('zoomview.update:', event);
+ });
+
+ // Overview waveform events
+
peaksInstance.on('overview.click', function(event) {
console.log('overview.click:', event);
});
diff --git a/demo/index.html b/demo/index.html
index f44670cd..c6cbf56f 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -523,6 +523,7 @@
Points
});
// Point events
+
peaksInstance.on('points.add', function(event) {
console.log('points.add:', event);
});
@@ -633,6 +634,10 @@ Points
console.log('zoomview.contextmenu:', event);
});
+ peaksInstance.on('zoomview.update', function(event) {
+ console.log('zoomview.update:', event);
+ });
+
// Overview waveform events
peaksInstance.on('overview.click', function(event) {
diff --git a/demo/overlay-segments.html b/demo/overlay-segments.html
index f35d1852..24afac5a 100644
--- a/demo/overlay-segments.html
+++ b/demo/overlay-segments.html
@@ -623,6 +623,10 @@ Points
console.log('zoomview.contextmenu:', event);
});
+ peaksInstance.on('zoomview.update', function(event) {
+ console.log('zoomview.update:', event);
+ });
+
// Overview waveform events
peaksInstance.on('overview.click', function(event) {
diff --git a/demo/zoomable-waveform.html b/demo/zoomable-waveform.html
index 7155a161..41073f82 100644
--- a/demo/zoomable-waveform.html
+++ b/demo/zoomable-waveform.html
@@ -174,6 +174,12 @@ Demo: Single Zoomable Waveform
view.setStartTime(seconds);
}
});
+
+ // Zoomview waveform events
+
+ peaksInstance.on('zoomview.update', function(event) {
+ console.log('zoomview.update:', event);
+ });
});
})(peaks);
diff --git a/doc/API.md b/doc/API.md
index 1b8ffabc..ac3940aa 100644
--- a/doc/API.md
+++ b/doc/API.md
@@ -92,6 +92,7 @@ This document describes the Peaks.js API, including configuration options, funct
- [zoomview.click](#zoomviewclick)
- [zoomview.dblclick](#zoomviewdblclick)
- [zoomview.contextmenu](#zoomviewcontextmenu)
+ - [zoomview.update](#zoomviewupdate)
- [zoom.update](#zoomupdate)
- [Point Events](#point-events)
- [points.add](#pointsadd)
@@ -1700,21 +1701,32 @@ instance.on('zoomview.contextmenu', function(event) {
});
```
-### `zoom.update`
+### `zoomview.update`
-This event is emitted when the zoom level in the zoomable waveform view changes.
+This event is emitted when the time range visible in the zoomable waveform view changes.
The `event` parameter contains:
-* `currentZoom`: The current zoom level, in samples per pixel
-* `previousZoom`: The previous zoom level, in samples per pixel
+* `startTime`: The time at the left edge of the waveform view.
+* `endTime`: The time at the right edge of the waveform view.
+
+Note that `startTime` may not be exactly the same value you set when calling [`view.setStartTime()`](#viewsetstarttimetime). This is because the time is rounded to a number of pixels at the view's zoom level.
```js
-instance.on('zoom.update', function(event) {
- console.log(`Zoom changed from ${event.previousZoom} to ${event.currentZoom}`);
+instance.on('zoomview.update', function(event) {
+ console.log(`Start time: ${event.startTime}, end time: ${event.endTime}`);
});
```
+### `zoom.update`
+
+This event is emitted when the zoom level in the zoomable waveform view changes.
+
+The `event` parameter contains:
+
+* `currentZoom`: The current zoom level, in samples per pixel
+* `previousZoom`: The previous zoom level, in samples per pixel
+
## Point Events
### `points.add`
diff --git a/src/scrollbar.js b/src/scrollbar.js
index 8e7dcf10..a88ca232 100644
--- a/src/scrollbar.js
+++ b/src/scrollbar.js
@@ -33,10 +33,10 @@ function Scrollbar(waveformData, container, peaks) {
this._onScrollboxDragStart = this._onScrollboxDragStart.bind(this);
this._onScrollboxDragMove = this._onScrollboxDragMove.bind(this);
this._onScrollboxDragEnd = this._onScrollboxDragEnd.bind(this);
- this._onZoomviewDisplaying = this._onZoomviewDisplaying.bind(this);
+ this._onZoomviewUpdate = this._onZoomviewUpdate.bind(this);
this._onScrollbarClick = this._onScrollbarClick.bind(this);
- peaks.on('zoomview.displaying', this._onZoomviewDisplaying);
+ this._peaks.on('zoomview.update', this._onZoomviewUpdate);
this._width = container.clientWidth;
this._height = container.clientHeight;
@@ -150,7 +150,7 @@ Scrollbar.prototype._onScrollboxDragMove = function() {
}
};
-Scrollbar.prototype._onZoomviewDisplaying = function(/* startTime , endTime */) {
+Scrollbar.prototype._onZoomviewUpdate = function(/* event */) {
if (!this._dragging) {
this._updateScrollbarWidthAndPosition();
}
@@ -218,6 +218,8 @@ Scrollbar.prototype.fitToContainer = function() {
};
Scrollbar.prototype.destroy = function() {
+ this._peaks.off('zoomview.update', this._onZoomviewUpdate);
+
this._layer.destroy();
this._stage.destroy();
diff --git a/src/waveform-overview.js b/src/waveform-overview.js
index e49b4bee..0cb0794a 100644
--- a/src/waveform-overview.js
+++ b/src/waveform-overview.js
@@ -30,13 +30,13 @@ function WaveformOverview(waveformData, container, peaks) {
self._onTimeUpdate = self._onTimeUpdate.bind(self);
self._onPlaying = self._onPlaying.bind(self);
self._onPause = self._onPause.bind(self);
- self._onZoomviewDisplaying = self._onZoomviewDisplaying.bind(self);
+ self._onZoomviewUpdate = self._onZoomviewUpdate.bind(self);
// Register event handlers
peaks.on('player.timeupdate', self._onTimeUpdate);
peaks.on('player.playing', self._onPlaying);
peaks.on('player.pause', self._onPause);
- peaks.on('zoomview.displaying', self._onZoomviewDisplaying);
+ peaks.on('zoomview.update', self._onZoomviewUpdate);
const time = self._peaks.player.getCurrentTime();
@@ -82,8 +82,8 @@ WaveformOverview.prototype._onPause = function(time) {
this._playheadLayer.stop(time);
};
-WaveformOverview.prototype._onZoomviewDisplaying = function(startTime, endTime) {
- this.showHighlight(startTime, endTime);
+WaveformOverview.prototype._onZoomviewUpdate = function(event) {
+ this.showHighlight(event.startTime, event.endTime);
};
WaveformOverview.prototype.showHighlight = function(startTime, endTime) {
@@ -156,7 +156,7 @@ WaveformOverview.prototype.destroy = function() {
this._peaks.off('player.playing', this._onPlaying);
this._peaks.off('player.pause', this._onPause);
this._peaks.off('player.timeupdate', this._onTimeUpdate);
- this._peaks.off('zoomview.displaying', this._onZoomviewDisplaying);
+ this._peaks.off('zoomview.update', this._onZoomviewUpdate);
this._mouseDragHandler.destroy();
diff --git a/src/waveform-zoomview.js b/src/waveform-zoomview.js
index c1cf7bad..6fa9c0a3 100644
--- a/src/waveform-zoomview.js
+++ b/src/waveform-zoomview.js
@@ -68,7 +68,10 @@ function WaveformZoomView(waveformData, container, peaks) {
self._onWheelCaptureVerticalScroll = self._onWheelCaptureVerticalScroll.bind(self);
self.setWheelMode(self._viewOptions.wheelMode);
- self._peaks.emit('zoomview.displaying', 0, self.getEndTime());
+ self._peaks.emit('zoomview.update', {
+ startTime: 0,
+ endTime: self.getEndTime()
+ });
}
WaveformZoomView.prototype = Object.create(WaveformView.prototype);
@@ -150,11 +153,11 @@ WaveformZoomView.prototype._onWheel = function(event) {
wheelEvent.preventDefault();
- const newFrameOffset = clamp(
+ const frameOffset = clamp(
this._frameOffset + Math.floor(delta), 0, this._pixelLength - this._width
);
- this.updateWaveform(newFrameOffset);
+ this.updateWaveform(frameOffset, false);
};
WaveformZoomView.prototype._onWheelCaptureVerticalScroll = function(event) {
@@ -165,11 +168,11 @@ WaveformZoomView.prototype._onWheelCaptureVerticalScroll = function(event) {
wheelEvent.preventDefault();
- const newFrameOffset = clamp(
+ const frameOffset = clamp(
this._frameOffset + Math.floor(delta), 0, this._pixelLength - this._width
);
- this.updateWaveform(newFrameOffset);
+ this.updateWaveform(frameOffset, false);
};
WaveformZoomView.prototype.setWaveformDragMode = function(mode) {
@@ -291,15 +294,17 @@ WaveformZoomView.prototype._syncPlayhead = function(time) {
// the keyboard)
const endThreshold = this._frameOffset + this._width - this._autoScrollOffset;
- if (pixelIndex >= endThreshold || pixelIndex < this._frameOffset) {
+ let frameOffset = this._frameOffset;
+
+ if (pixelIndex >= endThreshold || pixelIndex < frameOffset) {
// Put the playhead at 100 pixels from the left edge
- this._frameOffset = pixelIndex - this._autoScrollOffset;
+ frameOffset = pixelIndex - this._autoScrollOffset;
- if (this._frameOffset < 0) {
- this._frameOffset = 0;
+ if (frameOffset < 0) {
+ frameOffset = 0;
}
- this.updateWaveform(this._frameOffset);
+ this.updateWaveform(frameOffset, false);
}
}
};
@@ -387,9 +392,9 @@ WaveformZoomView.prototype.setZoom = function(options) {
const apexPixel = this.timeToPixels(apexTime);
- this._frameOffset = apexPixel - playheadOffsetPixels;
+ const frameOffset = apexPixel - playheadOffsetPixels;
- this.updateWaveform(this._frameOffset);
+ this.updateWaveform(frameOffset, true);
this._playheadLayer.zoomLevelChanged();
@@ -453,7 +458,7 @@ WaveformZoomView.prototype.setStartTime = function(time) {
time = 0;
}
- this.updateWaveform(this.timeToPixels(time));
+ this.updateWaveform(this.timeToPixels(time), false);
};
/**
@@ -483,7 +488,7 @@ WaveformZoomView.prototype.scrollWaveform = function(options) {
throw new TypeError('view.scrollWaveform(): Missing umber of pixels or seconds');
}
- this.updateWaveform(this._frameOffset + scrollAmount);
+ this.updateWaveform(this._frameOffset + scrollAmount, false);
};
/**
@@ -492,7 +497,7 @@ WaveformZoomView.prototype.scrollWaveform = function(options) {
* @param {Number} frameOffset The new frame offset, in pixels.
*/
-WaveformZoomView.prototype.updateWaveform = function(frameOffset) {
+WaveformZoomView.prototype.updateWaveform = function(frameOffset, forceUpdate) {
let upperLimit;
if (this._pixelLength < this._width) {
@@ -507,6 +512,10 @@ WaveformZoomView.prototype.updateWaveform = function(frameOffset) {
frameOffset = clamp(frameOffset, 0, upperLimit);
+ if (!forceUpdate && frameOffset === this._frameOffset) {
+ return;
+ }
+
this._frameOffset = frameOffset;
// Display playhead if it is within the zoom frame width.
@@ -528,7 +537,10 @@ WaveformZoomView.prototype.updateWaveform = function(frameOffset) {
this._segmentsLayer.updateSegments(frameStartTime, frameEndTime);
}
- this._peaks.emit('zoomview.displaying', frameStartTime, frameEndTime);
+ this._peaks.emit('zoomview.update', {
+ startTime: frameStartTime,
+ endTime: frameEndTime
+ });
};
WaveformZoomView.prototype.enableAutoScroll = function(enable, options) {
diff --git a/src/zoom-controller.js b/src/zoom-controller.js
index 1d5600eb..9a3b8afd 100644
--- a/src/zoom-controller.js
+++ b/src/zoom-controller.js
@@ -32,7 +32,7 @@ ZoomController.prototype.setZoomLevels = function(zoomLevels) {
*/
ZoomController.prototype.zoomIn = function() {
- this.setZoom(this._zoomLevelIndex - 1);
+ this.setZoom(this._zoomLevelIndex - 1, false);
};
/**
@@ -40,7 +40,7 @@ ZoomController.prototype.zoomIn = function() {
*/
ZoomController.prototype.zoomOut = function() {
- this.setZoom(this._zoomLevelIndex + 1);
+ this.setZoom(this._zoomLevelIndex + 1, false);
};
/**
diff --git a/test/api-zoom-spec.js b/test/api-zoom-spec.js
index 6862c2ec..55c1f02e 100644
--- a/test/api-zoom-spec.js
+++ b/test/api-zoom-spec.js
@@ -45,13 +45,14 @@ describe('Peaks.zoom', function() {
expect(p.zoom.getZoom()).to.equal(1);
});
- it('should emit a zoom.update event with the new zoom level index', function() {
+ it('should emit a zoom.update event with the new zoom level', function() {
const spy = sinon.spy();
p.on('zoom.update', spy);
p.zoom.setZoom(1);
- expect(spy).to.have.been.calledWith({ currentZoom: 1024, previousZoom: 512 });
+ expect(spy.callCount).to.equal(1);
+ expect(spy).calledWith({ currentZoom: 1024, previousZoom: 512 });
});
it('should limit the zoom level index value to the minimum valid index', function() {
@@ -80,6 +81,7 @@ describe('Peaks.zoom', function() {
p.on('zoom.update', spy);
p.zoom.zoomOut();
+ expect(spy.callCount).to.equal(1);
expect(spy).to.have.been.calledWith({ currentZoom: 1024, previousZoom: 512 });
});
});
@@ -93,7 +95,8 @@ describe('Peaks.zoom', function() {
p.on('zoom.update', spy);
p.zoom.zoomIn();
- expect(spy).to.have.been.calledWith({ currentZoom: 512, previousZoom: 1024 });
+ expect(spy.callCount).to.equal(1);
+ expect(spy).calledWith({ currentZoom: 512, previousZoom: 1024 });
});
});
});
diff --git a/test/waveform-zoomview-spec.js b/test/waveform-zoomview-spec.js
index 10b45f7f..1d96bc6c 100644
--- a/test/waveform-zoomview-spec.js
+++ b/test/waveform-zoomview-spec.js
@@ -64,6 +64,27 @@ describe('WaveformZoomView', function() {
expect(zoomview.getStartTime()).to.equal(0.0);
});
+
+ it('should emit a zoomview.update event if the start time has changed', function() {
+ const spy = sinon.spy();
+
+ p.on('zoomview.update', spy);
+
+ zoomview.setStartTime(5.0);
+
+ expect(spy.callCount).to.equal(1);
+ expect(spy.getCall(0).args[0].startTime).to.equal(zoomview.pixelsToTime(zoomview.timeToPixels(5.0)));
+ });
+
+ it('should not emit a zoomview.update event if the start time has not changed', function() {
+ const spy = sinon.spy();
+
+ p.on('zoomview.update', spy);
+
+ zoomview.setStartTime(-1.0);
+
+ expect(spy.callCount).to.equal(0);
+ });
});
context('with auto zoom level', function() {
@@ -76,6 +97,16 @@ describe('WaveformZoomView', function() {
expect(zoomview.getStartTime()).to.equal(0.0);
});
+
+ it('should not emit a zoomview.update event', function() {
+ const spy = sinon.spy();
+
+ p.on('zoomview.update', spy);
+
+ zoomview.setStartTime(5.0);
+
+ expect(spy.callCount).to.equal(0);
+ });
});
});
@@ -211,6 +242,10 @@ describe('WaveformZoomView', function() {
it('should scroll the waveform to the left', function() {
zoomview.updateWaveform(500);
+ const spy = sinon.spy();
+
+ p.on('zoomview.update', spy);
+
const distance = 100;
inputController.mouseDown({ x: 100, y: 50 });
@@ -221,9 +256,16 @@ describe('WaveformZoomView', function() {
expect(zoomview.getFrameOffset()).to.equal(400);
expect(zoomview.getStartTime()).to.equal(view.pixelsToTime(400));
+
+ expect(spy.callCount).to.equal(1);
+ expect(spy.getCall(0).args[0].startTime).to.equal(view.pixelsToTime(400));
});
it('should not scroll beyond the start of the waveform', function() {
+ const spy = sinon.spy();
+
+ p.on('zoomview.update', spy);
+
const distance = 200;
inputController.mouseDown({ x: 50, y: 50 });
@@ -232,6 +274,8 @@ describe('WaveformZoomView', function() {
expect(zoomview.getFrameOffset()).to.equal(0);
expect(zoomview.getStartTime()).to.equal(0);
+
+ expect(spy.callCount).to.equal(0);
});
it('should not scroll beyond the end of the waveform', function() {
@@ -258,6 +302,10 @@ describe('WaveformZoomView', function() {
context('when dragging the waveform view', function() {
it('should scroll the waveform to the right', function() {
+ const spy = sinon.spy();
+
+ p.on('zoomview.update', spy);
+
const distance = 100;
inputController.mouseDown({ x: 100, y: 50 });
@@ -268,11 +316,18 @@ describe('WaveformZoomView', function() {
expect(zoomview.getFrameOffset()).to.equal(100);
expect(zoomview.getStartTime()).to.equal(view.pixelsToTime(distance));
+
+ expect(spy.callCount).to.equal(1);
+ expect(spy.getCall(0).args[0].startTime).to.equal(view.pixelsToTime(distance));
});
it('should scroll the waveform to the left', function() {
zoomview.updateWaveform(500);
+ const spy = sinon.spy();
+
+ p.on('zoomview.update', spy);
+
const distance = 100;
inputController.mouseDown({ x: 100, y: 50 });
@@ -283,11 +338,18 @@ describe('WaveformZoomView', function() {
expect(zoomview.getFrameOffset()).to.equal(400);
expect(zoomview.getStartTime()).to.equal(view.pixelsToTime(400));
+
+ expect(spy.callCount).to.equal(1);
+ expect(spy.getCall(0).args[0].startTime).to.equal(view.pixelsToTime(400));
});
it('should prevent the start time from becoming less than zero', function() {
zoomview.updateWaveform(100);
+ const spy = sinon.spy();
+
+ p.on('zoomview.update', spy);
+
const distance = 150;
inputController.mouseDown({ x: 100, y: 50 });
@@ -296,6 +358,9 @@ describe('WaveformZoomView', function() {
expect(zoomview.getFrameOffset()).to.equal(0);
expect(zoomview.getStartTime()).to.equal(0);
+
+ expect(spy.callCount).to.equal(1);
+ expect(spy.getCall(0).args[0].startTime).to.equal(zoomview.pixelsToTime(0));
});
});
});