wavesurfer.js 5.2.0 → 6.0.0
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/CHANGES.md +22 -0
- package/README.md +10 -0
- package/dist/plugin/wavesurfer.cursor.js +52 -50
- package/dist/plugin/wavesurfer.cursor.js.map +1 -1
- package/dist/plugin/wavesurfer.cursor.min.js +2 -2
- package/dist/plugin/wavesurfer.cursor.min.js.map +1 -1
- package/dist/plugin/wavesurfer.elan.js +9 -6
- package/dist/plugin/wavesurfer.elan.js.map +1 -1
- package/dist/plugin/wavesurfer.elan.min.js +2 -2
- package/dist/plugin/wavesurfer.elan.min.js.map +1 -1
- package/dist/plugin/wavesurfer.markers.js +141 -25
- package/dist/plugin/wavesurfer.markers.js.map +1 -1
- package/dist/plugin/wavesurfer.markers.min.js +2 -2
- package/dist/plugin/wavesurfer.markers.min.js.map +1 -1
- package/dist/plugin/wavesurfer.mediasession.js +5 -5
- package/dist/plugin/wavesurfer.mediasession.min.js +2 -2
- package/dist/plugin/wavesurfer.mediasession.min.js.map +1 -1
- package/dist/plugin/wavesurfer.microphone.js +4 -4
- package/dist/plugin/wavesurfer.microphone.min.js +2 -2
- package/dist/plugin/wavesurfer.microphone.min.js.map +1 -1
- package/dist/plugin/wavesurfer.minimap.js +25 -22
- package/dist/plugin/wavesurfer.minimap.js.map +1 -1
- package/dist/plugin/wavesurfer.minimap.min.js +2 -2
- package/dist/plugin/wavesurfer.minimap.min.js.map +1 -1
- package/dist/plugin/wavesurfer.playhead.js +4 -4
- package/dist/plugin/wavesurfer.playhead.min.js +2 -2
- package/dist/plugin/wavesurfer.playhead.min.js.map +1 -1
- package/dist/plugin/wavesurfer.regions.js +53 -16
- package/dist/plugin/wavesurfer.regions.js.map +1 -1
- package/dist/plugin/wavesurfer.regions.min.js +2 -2
- package/dist/plugin/wavesurfer.regions.min.js.map +1 -1
- package/dist/plugin/wavesurfer.spectrogram.js +70 -57
- package/dist/plugin/wavesurfer.spectrogram.js.map +1 -1
- package/dist/plugin/wavesurfer.spectrogram.min.js +2 -2
- package/dist/plugin/wavesurfer.spectrogram.min.js.map +1 -1
- package/dist/plugin/wavesurfer.timeline.js +39 -44
- package/dist/plugin/wavesurfer.timeline.js.map +1 -1
- package/dist/plugin/wavesurfer.timeline.min.js +2 -2
- package/dist/plugin/wavesurfer.timeline.min.js.map +1 -1
- package/dist/wavesurfer-html-init.js +5 -5
- package/dist/wavesurfer-html-init.min.js +2 -2
- package/dist/wavesurfer-html-init.min.js.map +1 -1
- package/dist/wavesurfer.js +209 -121
- package/dist/wavesurfer.js.map +1 -1
- package/dist/wavesurfer.min.js +2 -2
- package/dist/wavesurfer.min.js.map +1 -1
- package/package.json +23 -23
- package/src/drawer.canvasentry.js +30 -6
- package/src/drawer.js +1 -0
- package/src/drawer.multicanvas.js +19 -8
- package/src/mediaelement.js +1 -1
- package/src/plugin/cursor/index.js +68 -70
- package/src/plugin/markers/index.js +112 -23
- package/src/plugin/minimap/index.js +24 -21
- package/src/plugin/regions/index.js +30 -3
- package/src/plugin/regions/region.js +13 -4
- package/src/plugin/spectrogram/index.js +65 -50
- package/src/wavesurfer.js +31 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wavesurfer.js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Interactive navigable audio visualization using Web Audio and Canvas",
|
|
5
5
|
"main": "dist/wavesurfer.js",
|
|
6
6
|
"directories": {
|
|
@@ -55,17 +55,17 @@
|
|
|
55
55
|
"visualization"
|
|
56
56
|
],
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@babel/core": "^7.
|
|
59
|
-
"@babel/
|
|
60
|
-
"@babel/
|
|
61
|
-
"@
|
|
62
|
-
"babel
|
|
63
|
-
"
|
|
58
|
+
"@babel/core": "^7.17.0",
|
|
59
|
+
"@babel/eslint-parser": "^7.17.0",
|
|
60
|
+
"@babel/plugin-proposal-class-properties": "^7.16.7",
|
|
61
|
+
"@babel/preset-env": "^7.16.11",
|
|
62
|
+
"@babel/register": "^7.17.0",
|
|
63
|
+
"@chiragrupani/karma-chromium-edge-launcher": "^2.2.1",
|
|
64
|
+
"babel-loader": "^8.2.3",
|
|
64
65
|
"babel-plugin-add-module-exports": "^1.0.4",
|
|
65
|
-
"babel-plugin-istanbul": "^6.
|
|
66
|
+
"babel-plugin-istanbul": "^6.1.1",
|
|
66
67
|
"babel-plugin-proxy": "^1.1.0",
|
|
67
|
-
"
|
|
68
|
-
"date-fns": "^2.23.0",
|
|
68
|
+
"date-fns": "^2.28.0",
|
|
69
69
|
"debounce": "^1.2.1",
|
|
70
70
|
"esdoc": "^1.1.0",
|
|
71
71
|
"esdoc-accessor-plugin": "^1.0.0",
|
|
@@ -74,24 +74,24 @@
|
|
|
74
74
|
"esdoc-ecmascript-proposal-plugin": "^1.0.0",
|
|
75
75
|
"esdoc-integrate-test-plugin": "^1.0.0",
|
|
76
76
|
"esdoc-standard-plugin": "^1.0.0",
|
|
77
|
-
"eslint": "^
|
|
78
|
-
"htmlhint": "^
|
|
77
|
+
"eslint": "^8.8.0",
|
|
78
|
+
"htmlhint": "^1.1.2",
|
|
79
79
|
"in-publish": "^2.0.1",
|
|
80
|
-
"jasmine-core": "^
|
|
81
|
-
"karma": "^6.3.
|
|
80
|
+
"jasmine-core": "^4.0.0",
|
|
81
|
+
"karma": "^6.3.15",
|
|
82
82
|
"karma-chrome-launcher": "3.1.0",
|
|
83
|
-
"karma-coverage": "^2.
|
|
84
|
-
"karma-firefox-launcher": "^2.1.
|
|
83
|
+
"karma-coverage": "^2.1.1",
|
|
84
|
+
"karma-firefox-launcher": "^2.1.2",
|
|
85
85
|
"karma-jasmine": "4.0.1",
|
|
86
|
-
"karma-jasmine-matchers": "
|
|
87
|
-
"karma-verbose-reporter": "0.0.
|
|
86
|
+
"karma-jasmine-matchers": "5.0.0",
|
|
87
|
+
"karma-verbose-reporter": "0.0.8",
|
|
88
88
|
"karma-webpack": "^5.0.0",
|
|
89
|
-
"lint-staged": "^
|
|
90
|
-
"load-script": "^
|
|
89
|
+
"lint-staged": "^12.3.3",
|
|
90
|
+
"load-script": "^2.0.0",
|
|
91
91
|
"pre-commit": "^1.2.2",
|
|
92
|
-
"webpack": "^5.
|
|
93
|
-
"webpack-cli": "^4.
|
|
94
|
-
"webpack-dev-server": "^4.
|
|
92
|
+
"webpack": "^5.68.0",
|
|
93
|
+
"webpack-cli": "^4.9.2",
|
|
94
|
+
"webpack-dev-server": "^4.7.4",
|
|
95
95
|
"webpack-merge": "^5.8.0"
|
|
96
96
|
},
|
|
97
97
|
"homepage": "https://wavesurfer-js.org",
|
|
@@ -145,18 +145,42 @@ export default class CanvasEntry {
|
|
|
145
145
|
|
|
146
146
|
/**
|
|
147
147
|
* Set the fill styles for wave and progress
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* @param {?string} progressColor Fill color for the progress canvas
|
|
148
|
+
* @param {string|string[]} waveColor Fill color for the wave canvas,
|
|
149
|
+
* or an array of colors to apply as a gradient
|
|
150
|
+
* @param {?string|string[]} progressColor Fill color for the progress canvas,
|
|
151
|
+
* or an array of colors to apply as a gradient
|
|
151
152
|
*/
|
|
152
153
|
setFillStyles(waveColor, progressColor) {
|
|
153
|
-
this.waveCtx.fillStyle = waveColor;
|
|
154
|
+
this.waveCtx.fillStyle = this.getFillStyle(this.waveCtx, waveColor);
|
|
154
155
|
|
|
155
156
|
if (this.hasProgressCanvas) {
|
|
156
|
-
this.progressCtx.fillStyle = progressColor;
|
|
157
|
+
this.progressCtx.fillStyle = this.getFillStyle(this.progressCtx, progressColor);
|
|
157
158
|
}
|
|
158
159
|
}
|
|
159
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Utility function to handle wave color arguments
|
|
163
|
+
*
|
|
164
|
+
* When the color argument type is a string, it will be returned as is.
|
|
165
|
+
* Otherwise, it will be treated as an array, and a canvas gradient will
|
|
166
|
+
* be returned
|
|
167
|
+
*
|
|
168
|
+
* @since 5.3.0
|
|
169
|
+
* @param {CanvasRenderingContext2D} ctx Rendering context of target canvas
|
|
170
|
+
* @param {string|string[]} color Fill color for the wave canvas, or an array of colors to apply as a gradient
|
|
171
|
+
* @returns {string|CanvasGradient} Returns a string fillstyle value, or a canvas gradient
|
|
172
|
+
*/
|
|
173
|
+
getFillStyle(ctx, color) {
|
|
174
|
+
if (typeof color == 'string') {
|
|
175
|
+
return color;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const waveGradient = ctx.createLinearGradient(0, 0, 0, ctx.canvas.height);
|
|
179
|
+
color.forEach((value, index) => waveGradient.addColorStop((index / color.length), value));
|
|
180
|
+
|
|
181
|
+
return waveGradient;
|
|
182
|
+
}
|
|
183
|
+
|
|
160
184
|
/**
|
|
161
185
|
* Set the canvas transforms for wave and progress
|
|
162
186
|
*
|
|
@@ -357,7 +381,7 @@ export default class CanvasEntry {
|
|
|
357
381
|
ctx.lineTo(
|
|
358
382
|
(canvasStart - first) * scale,
|
|
359
383
|
halfOffset -
|
|
360
|
-
|
|
384
|
+
Math.round((peaks[2 * canvasStart + 1] || 0) / absmaxHalf)
|
|
361
385
|
);
|
|
362
386
|
|
|
363
387
|
ctx.closePath();
|
package/src/drawer.js
CHANGED
|
@@ -69,6 +69,7 @@ export default class Drawer extends util.Observer {
|
|
|
69
69
|
if (this.params.fillParent || this.params.scrollParent) {
|
|
70
70
|
this.style(this.wrapper, {
|
|
71
71
|
width: '100%',
|
|
72
|
+
cursor: this.params.hideCursor ? 'none' : 'auto',
|
|
72
73
|
overflowX: this.params.hideScrollbar ? 'hidden' : 'auto',
|
|
73
74
|
overflowY: 'hidden'
|
|
74
75
|
});
|
|
@@ -305,21 +305,32 @@ export default class MultiCanvas extends Drawer {
|
|
|
305
305
|
const scale = length / this.width;
|
|
306
306
|
const first = start;
|
|
307
307
|
const last = end;
|
|
308
|
-
let
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
308
|
+
let peakIndex = first;
|
|
309
|
+
for (peakIndex; peakIndex < last; peakIndex += step) {
|
|
310
|
+
|
|
311
|
+
// search for the highest peak in the range this bar falls into
|
|
312
|
+
let peak = 0;
|
|
313
|
+
let peakIndexRange = Math.floor(peakIndex * scale) * peakIndexScale; // start index
|
|
314
|
+
const peakIndexEnd = Math.floor((peakIndex + step) * scale) * peakIndexScale;
|
|
315
|
+
do { // do..while makes sure at least one peak is always evaluated
|
|
316
|
+
const newPeak = peaks[peakIndexRange];
|
|
317
|
+
if (newPeak > peak) {
|
|
318
|
+
peak = newPeak; // higher
|
|
319
|
+
}
|
|
320
|
+
peakIndexRange += peakIndexScale; // skip every other value for negatives
|
|
321
|
+
} while (peakIndexRange < peakIndexEnd);
|
|
322
|
+
|
|
323
|
+
// calculate the height of this bar according to the highest peak found
|
|
313
324
|
let h = Math.round((peak / absmax) * halfH);
|
|
314
325
|
|
|
315
|
-
|
|
316
|
-
|
|
326
|
+
// in case of silences, allow the user to specify that we
|
|
327
|
+
// always draw *something* (normally a 1px high bar)
|
|
317
328
|
if (h == 0 && this.params.barMinHeight) {
|
|
318
329
|
h = this.params.barMinHeight;
|
|
319
330
|
}
|
|
320
331
|
|
|
321
332
|
this.fillRect(
|
|
322
|
-
|
|
333
|
+
peakIndex + this.halfPixel,
|
|
323
334
|
halfH - h + offsetY,
|
|
324
335
|
bar + this.halfPixel,
|
|
325
336
|
h * 2,
|
package/src/mediaelement.js
CHANGED
|
@@ -275,7 +275,7 @@ export default class MediaElement extends WebAudio {
|
|
|
275
275
|
* @param {number} start Position to start at in seconds
|
|
276
276
|
*/
|
|
277
277
|
seekTo(start) {
|
|
278
|
-
if (start != null) {
|
|
278
|
+
if (start != null && !isNaN(start)) {
|
|
279
279
|
this.media.currentTime = start;
|
|
280
280
|
}
|
|
281
281
|
this.clearPlayEnd();
|
|
@@ -86,14 +86,15 @@ export default class CursorPlugin {
|
|
|
86
86
|
* @param {object} e Mouse move event
|
|
87
87
|
*/
|
|
88
88
|
_onMousemove = e => {
|
|
89
|
-
const
|
|
89
|
+
const event = this.util.withOrientation(e, this.wavesurfer.params.vertical);
|
|
90
|
+
const bbox = this.wrapper.getBoundingClientRect();
|
|
90
91
|
let y = 0;
|
|
91
|
-
let x =
|
|
92
|
-
let flip = bbox.right <
|
|
92
|
+
let x = this.wrapper.scrollLeft + event.clientX - bbox.left;
|
|
93
|
+
let flip = bbox.right < event.clientX + this.displayTime.getBoundingClientRect().width;
|
|
93
94
|
|
|
94
95
|
if (this.params.showTime && this.params.followCursorY) {
|
|
95
96
|
// follow y-position of the mouse
|
|
96
|
-
y =
|
|
97
|
+
y = event.clientY - (bbox.top + bbox.height / 2);
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
this.updateCursorPosition(x, y, flip);
|
|
@@ -119,6 +120,7 @@ export default class CursorPlugin {
|
|
|
119
120
|
constructor(params, ws) {
|
|
120
121
|
this.wavesurfer = ws;
|
|
121
122
|
this.style = ws.util.style;
|
|
123
|
+
this.util = ws.util;
|
|
122
124
|
/**
|
|
123
125
|
* The cursor HTML element
|
|
124
126
|
*
|
|
@@ -141,14 +143,38 @@ export default class CursorPlugin {
|
|
|
141
143
|
this.params = Object.assign({}, this.defaultParams, params);
|
|
142
144
|
}
|
|
143
145
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
_onReady() {
|
|
147
|
+
this.wrapper = this.wavesurfer.drawer.wrapper;
|
|
148
|
+
this.cursor = this.util.withOrientation(this.wrapper.appendChild(
|
|
149
|
+
document.createElement('cursor'),
|
|
150
|
+
), this.wavesurfer.params.vertical);
|
|
151
|
+
|
|
152
|
+
this.style(this.cursor,
|
|
153
|
+
Object.assign(
|
|
154
|
+
{
|
|
155
|
+
position: 'absolute',
|
|
156
|
+
zIndex: this.params.zIndex,
|
|
157
|
+
left: 0,
|
|
158
|
+
top: 0,
|
|
159
|
+
bottom: 0,
|
|
160
|
+
width: '0',
|
|
161
|
+
display: 'flex',
|
|
162
|
+
borderRightStyle: this.params.style,
|
|
163
|
+
borderRightWidth: this.params.width,
|
|
164
|
+
borderRightColor: this.params.color,
|
|
165
|
+
opacity: this.params.opacity,
|
|
166
|
+
pointerEvents: 'none'
|
|
167
|
+
},
|
|
168
|
+
this.params.customStyle
|
|
169
|
+
)
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
if (this.params.showTime) {
|
|
173
|
+
this.showTime = this.util.withOrientation(this.wrapper.appendChild(
|
|
174
|
+
document.createElement('showTitle')
|
|
175
|
+
), this.wavesurfer.params.vertical);
|
|
150
176
|
this.style(
|
|
151
|
-
|
|
177
|
+
this.showTime,
|
|
152
178
|
Object.assign(
|
|
153
179
|
{
|
|
154
180
|
position: 'absolute',
|
|
@@ -156,53 +182,32 @@ export default class CursorPlugin {
|
|
|
156
182
|
left: 0,
|
|
157
183
|
top: 0,
|
|
158
184
|
bottom: 0,
|
|
159
|
-
width: '
|
|
185
|
+
width: 'auto',
|
|
160
186
|
display: 'flex',
|
|
161
|
-
borderRightStyle: this.params.style,
|
|
162
|
-
borderRightWidth: this.params.width,
|
|
163
|
-
borderRightColor: this.params.color,
|
|
164
187
|
opacity: this.params.opacity,
|
|
165
|
-
pointerEvents: 'none'
|
|
188
|
+
pointerEvents: 'none',
|
|
189
|
+
height: '100%'
|
|
166
190
|
},
|
|
167
191
|
this.params.customStyle
|
|
168
192
|
)
|
|
169
|
-
)
|
|
170
|
-
);
|
|
171
|
-
if (this.params.showTime) {
|
|
172
|
-
this.showTime = this.wrapper.appendChild(
|
|
173
|
-
this.style(
|
|
174
|
-
document.createElement('showTitle'),
|
|
175
|
-
Object.assign(
|
|
176
|
-
{
|
|
177
|
-
position: 'absolute',
|
|
178
|
-
zIndex: this.params.zIndex,
|
|
179
|
-
left: 0,
|
|
180
|
-
top: 0,
|
|
181
|
-
bottom: 0,
|
|
182
|
-
width: 'auto',
|
|
183
|
-
display: 'flex',
|
|
184
|
-
opacity: this.params.opacity,
|
|
185
|
-
pointerEvents: 'none',
|
|
186
|
-
height: '100%'
|
|
187
|
-
},
|
|
188
|
-
this.params.customStyle
|
|
189
|
-
)
|
|
190
|
-
)
|
|
191
193
|
);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
194
|
+
|
|
195
|
+
this.displayTime = this.util.withOrientation(this.showTime.appendChild(
|
|
196
|
+
document.createElement('div'),
|
|
197
|
+
), this.wavesurfer.params.vertical);
|
|
198
|
+
|
|
199
|
+
this.style(this.displayTime,
|
|
200
|
+
Object.assign(
|
|
201
|
+
{
|
|
202
|
+
display: 'inline',
|
|
203
|
+
pointerEvents: 'none',
|
|
204
|
+
margin: 'auto',
|
|
205
|
+
visibility: 'hidden' // initial value will be hidden just for measuring purpose
|
|
206
|
+
},
|
|
207
|
+
this.params.customShowTimeStyle
|
|
204
208
|
)
|
|
205
209
|
);
|
|
210
|
+
|
|
206
211
|
// initial value to measure display width
|
|
207
212
|
this.displayTime.innerHTML = this.formatTime(0);
|
|
208
213
|
}
|
|
@@ -216,6 +221,17 @@ export default class CursorPlugin {
|
|
|
216
221
|
}
|
|
217
222
|
}
|
|
218
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Initialise the plugin (used by the Plugin API)
|
|
226
|
+
*/
|
|
227
|
+
init() {
|
|
228
|
+
if (this.wavesurfer.isReady) {
|
|
229
|
+
this._onReady();
|
|
230
|
+
} else {
|
|
231
|
+
this.wavesurfer.once('ready', () => this._onReady());
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
219
235
|
/**
|
|
220
236
|
* Destroy the plugin (used by the Plugin API)
|
|
221
237
|
*/
|
|
@@ -253,10 +269,10 @@ export default class CursorPlugin {
|
|
|
253
269
|
(duration / this.wavesurfer.drawer.width) * scrollWidth;
|
|
254
270
|
|
|
255
271
|
const timeValue =
|
|
256
|
-
Math.max(0, (xpos / elementWidth) * duration) + scrollTime;
|
|
272
|
+
Math.max(0, ((xpos - this.wrapper.scrollLeft) / elementWidth) * duration) + scrollTime;
|
|
257
273
|
const formatValue = this.formatTime(timeValue);
|
|
258
274
|
if (flip) {
|
|
259
|
-
const textOffset = this.
|
|
275
|
+
const textOffset = this.displayTime.getBoundingClientRect().width;
|
|
260
276
|
xpos -= textOffset;
|
|
261
277
|
}
|
|
262
278
|
this.style(this.showTime, {
|
|
@@ -318,22 +334,4 @@ export default class CursorPlugin {
|
|
|
318
334
|
].join(':')
|
|
319
335
|
);
|
|
320
336
|
}
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Get outer width of given element.
|
|
324
|
-
*
|
|
325
|
-
* @param {DOM} element DOM Element
|
|
326
|
-
* @returns {number} outer width
|
|
327
|
-
*/
|
|
328
|
-
outerWidth(element) {
|
|
329
|
-
if (!element) {
|
|
330
|
-
return 0;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
let width = element.offsetWidth;
|
|
334
|
-
let style = getComputedStyle(element);
|
|
335
|
-
|
|
336
|
-
width += parseInt(style.marginLeft + style.marginRight);
|
|
337
|
-
return width;
|
|
338
|
-
}
|
|
339
337
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
/**
|
|
3
2
|
* @typedef {Object} MarkerParams
|
|
4
3
|
* @desc The parameters used to describe a marker.
|
|
@@ -8,6 +7,7 @@
|
|
|
8
7
|
* @property {?color} string Background color for marker
|
|
9
8
|
* @property {?position} string "top" or "bottom", defaults to "bottom"
|
|
10
9
|
* @property {?markerElement} element An HTML element to display instead of the default marker image
|
|
10
|
+
* @property {?draggable} boolean Set marker as draggable, defaults to false
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
|
|
@@ -41,6 +41,8 @@ export default class MarkersPlugin {
|
|
|
41
41
|
* @typedef {Object} MarkersPluginParams
|
|
42
42
|
* @property {?MarkerParams[]} markers Initial set of markers
|
|
43
43
|
* @fires MarkersPlugin#marker-click
|
|
44
|
+
* @fires MarkersPlugin#marker-drag
|
|
45
|
+
* @fires MarkersPlugin#marker-drop
|
|
44
46
|
*/
|
|
45
47
|
|
|
46
48
|
/**
|
|
@@ -78,8 +80,10 @@ export default class MarkersPlugin {
|
|
|
78
80
|
this.wavesurfer = ws;
|
|
79
81
|
this.util = ws.util;
|
|
80
82
|
this.style = this.util.style;
|
|
83
|
+
this.markerLineWidth = 1;
|
|
81
84
|
this.markerWidth = 11;
|
|
82
85
|
this.markerHeight = 22;
|
|
86
|
+
this.dragging = false;
|
|
83
87
|
|
|
84
88
|
|
|
85
89
|
this._onResize = () => {
|
|
@@ -94,6 +98,16 @@ export default class MarkersPlugin {
|
|
|
94
98
|
window.addEventListener('resize', this._onResize, true);
|
|
95
99
|
window.addEventListener('orientationchange', this._onResize, true);
|
|
96
100
|
this.wavesurfer.on('zoom', this._onResize);
|
|
101
|
+
|
|
102
|
+
if (!this.markers.find(marker => marker.draggable)){
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this.onMouseMove = (e) => this._onMouseMove(e);
|
|
107
|
+
window.addEventListener('mousemove', this.onMouseMove);
|
|
108
|
+
|
|
109
|
+
this.onMouseUp = (e) => this._onMouseUp(e);
|
|
110
|
+
window.addEventListener("mouseup", this.onMouseUp);
|
|
97
111
|
};
|
|
98
112
|
|
|
99
113
|
this.markers = [];
|
|
@@ -123,6 +137,13 @@ export default class MarkersPlugin {
|
|
|
123
137
|
window.removeEventListener('resize', this._onResize, true);
|
|
124
138
|
window.removeEventListener('orientationchange', this._onResize, true);
|
|
125
139
|
|
|
140
|
+
if (this.onMouseMove) {
|
|
141
|
+
window.removeEventListener('mousemove', this.onMouseMove);
|
|
142
|
+
}
|
|
143
|
+
if (this.onMouseUp) {
|
|
144
|
+
window.removeEventListener("mouseup", this.onMouseUp);
|
|
145
|
+
}
|
|
146
|
+
|
|
126
147
|
this.clear();
|
|
127
148
|
}
|
|
128
149
|
|
|
@@ -137,14 +158,10 @@ export default class MarkersPlugin {
|
|
|
137
158
|
time: params.time,
|
|
138
159
|
label: params.label,
|
|
139
160
|
color: params.color || DEFAULT_FILL_COLOR,
|
|
140
|
-
position: params.position || DEFAULT_POSITION
|
|
161
|
+
position: params.position || DEFAULT_POSITION,
|
|
162
|
+
draggable: !!params.draggable
|
|
141
163
|
};
|
|
142
164
|
|
|
143
|
-
if (params.markerElement) {
|
|
144
|
-
this.markerWidth = params.markerElement.width;
|
|
145
|
-
this.markerHeight = params.markerElement.height;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
165
|
marker.el = this._createMarkerElement(marker, params.markerElement);
|
|
149
166
|
|
|
150
167
|
this.wrapper.appendChild(marker.el);
|
|
@@ -199,7 +216,6 @@ export default class MarkersPlugin {
|
|
|
199
216
|
|
|
200
217
|
_createMarkerElement(marker, markerElement) {
|
|
201
218
|
let label = marker.label;
|
|
202
|
-
let time = marker.time;
|
|
203
219
|
|
|
204
220
|
const el = document.createElement('marker');
|
|
205
221
|
el.className = "wavesurfer-marker";
|
|
@@ -213,17 +229,22 @@ export default class MarkersPlugin {
|
|
|
213
229
|
});
|
|
214
230
|
|
|
215
231
|
const line = document.createElement('div');
|
|
232
|
+
const width = markerElement ? markerElement.width : this.markerWidth;
|
|
233
|
+
marker.offset = (width - this.markerLineWidth) / 2;
|
|
216
234
|
this.style(line, {
|
|
217
235
|
"flex-grow": 1,
|
|
218
|
-
"margin-left":
|
|
236
|
+
"margin-left": marker.offset + "px",
|
|
219
237
|
background: "black",
|
|
220
|
-
width: "
|
|
238
|
+
width: this.markerLineWidth + "px",
|
|
221
239
|
opacity: 0.1
|
|
222
240
|
});
|
|
223
241
|
el.appendChild(line);
|
|
224
242
|
|
|
225
243
|
const labelDiv = document.createElement('div');
|
|
226
244
|
const point = markerElement || this._createPointerSVG(marker.color, marker.position);
|
|
245
|
+
if (marker.draggable){
|
|
246
|
+
point.draggable = false;
|
|
247
|
+
}
|
|
227
248
|
labelDiv.appendChild(point);
|
|
228
249
|
|
|
229
250
|
if ( label ) {
|
|
@@ -246,31 +267,99 @@ export default class MarkersPlugin {
|
|
|
246
267
|
|
|
247
268
|
labelDiv.addEventListener("click", e => {
|
|
248
269
|
e.stopPropagation();
|
|
249
|
-
|
|
270
|
+
// Click event is caught when the marker-drop event was dispatched.
|
|
271
|
+
// Drop event was dispatched at this moment, but this.dragging
|
|
272
|
+
// is waiting for the next tick to set as false
|
|
273
|
+
if (this.dragging){
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
this.wavesurfer.setCurrentTime(marker.time);
|
|
250
277
|
this.wavesurfer.fireEvent("marker-click", marker, e);
|
|
251
278
|
});
|
|
252
279
|
|
|
280
|
+
if (marker.draggable) {
|
|
281
|
+
labelDiv.addEventListener("mousedown", e => {
|
|
282
|
+
this.selectedMarker = marker;
|
|
283
|
+
});
|
|
284
|
+
}
|
|
253
285
|
return el;
|
|
254
286
|
}
|
|
255
287
|
|
|
256
288
|
_updateMarkerPositions() {
|
|
257
|
-
const duration = this.wavesurfer.getDuration();
|
|
258
|
-
|
|
259
289
|
for ( let i = 0 ; i < this.markers.length; i++ ) {
|
|
260
290
|
let marker = this.markers[i];
|
|
261
|
-
|
|
262
|
-
this.wavesurfer.drawer.width /
|
|
263
|
-
this.wavesurfer.params.pixelRatio;
|
|
264
|
-
|
|
265
|
-
const positionPct = Math.min(marker.time / duration, 1);
|
|
266
|
-
const leftPx = ((elementWidth * positionPct) - (this.markerWidth / 2));
|
|
267
|
-
this.style(marker.el, {
|
|
268
|
-
"left": leftPx + "px",
|
|
269
|
-
"max-width": (elementWidth - leftPx) + "px"
|
|
270
|
-
});
|
|
291
|
+
this._updateMarkerPosition(marker);
|
|
271
292
|
}
|
|
272
293
|
}
|
|
273
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Update a marker position based on its time property.
|
|
297
|
+
*
|
|
298
|
+
* @private
|
|
299
|
+
* @param {MarkerParams} params The marker to update.
|
|
300
|
+
* @returns {void}
|
|
301
|
+
*/
|
|
302
|
+
_updateMarkerPosition(params) {
|
|
303
|
+
const duration = this.wavesurfer.getDuration();
|
|
304
|
+
const elementWidth =
|
|
305
|
+
this.wavesurfer.drawer.width /
|
|
306
|
+
this.wavesurfer.params.pixelRatio;
|
|
307
|
+
|
|
308
|
+
const positionPct = Math.min(params.time / duration, 1);
|
|
309
|
+
const leftPx = ((elementWidth * positionPct) - params.offset);
|
|
310
|
+
this.style(params.el, {
|
|
311
|
+
"left": leftPx + "px",
|
|
312
|
+
"max-width": (elementWidth - leftPx) + "px"
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Fires `marker-drag` event, update the `time` property for the
|
|
318
|
+
* selected marker based on the mouse position, and calls to update
|
|
319
|
+
* its position.
|
|
320
|
+
*
|
|
321
|
+
* @private
|
|
322
|
+
* @param {MouseEvent} event The mouse event.
|
|
323
|
+
* @returns {void}
|
|
324
|
+
*/
|
|
325
|
+
_onMouseMove(event) {
|
|
326
|
+
if (!this.selectedMarker){
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (!this.dragging){
|
|
330
|
+
this.dragging = true;
|
|
331
|
+
this.wavesurfer.fireEvent("marker-drag", this.selectedMarker, event);
|
|
332
|
+
}
|
|
333
|
+
this.selectedMarker.time = this.wavesurfer.drawer.handleEvent(event) * this.wavesurfer.getDuration();
|
|
334
|
+
this._updateMarkerPositions();
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Fires `marker-drop` event and unselect the dragged marker.
|
|
339
|
+
*
|
|
340
|
+
* @private
|
|
341
|
+
* @param {MouseEvent} event The mouse event.
|
|
342
|
+
* @returns {void}
|
|
343
|
+
*/
|
|
344
|
+
_onMouseUp(event) {
|
|
345
|
+
if (this.selectedMarker) {
|
|
346
|
+
setTimeout(() => {
|
|
347
|
+
this.selectedMarker = false;
|
|
348
|
+
this.dragging = false;
|
|
349
|
+
}, 0);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (!this.dragging) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
event.stopPropagation();
|
|
357
|
+
const duration = this.wavesurfer.getDuration();
|
|
358
|
+
this.selectedMarker.time = this.wavesurfer.drawer.handleEvent(event) * duration;
|
|
359
|
+
this._updateMarkerPositions();
|
|
360
|
+
this.wavesurfer.fireEvent("marker-drop", this.selectedMarker, event);
|
|
361
|
+
}
|
|
362
|
+
|
|
274
363
|
/**
|
|
275
364
|
* Remove all markers
|
|
276
365
|
*/
|