wavesurfer.js 5.0.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 +48 -0
- package/README.md +10 -0
- package/dist/plugin/wavesurfer.cursor.js +53 -51
- 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 +10 -7
- 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 +151 -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 +6 -6
- package/dist/plugin/wavesurfer.mediasession.js.map +1 -1
- 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 +5 -5
- package/dist/plugin/wavesurfer.microphone.js.map +1 -1
- 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 +26 -23
- 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 +5 -5
- package/dist/plugin/wavesurfer.playhead.js.map +1 -1
- 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 +92 -23
- 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 +104 -85
- 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 +67 -57
- 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 +6 -6
- package/dist/wavesurfer-html-init.js.map +1 -1
- package/dist/wavesurfer-html-init.min.js +2 -2
- package/dist/wavesurfer-html-init.min.js.map +1 -1
- package/dist/wavesurfer.js +300 -134
- 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 +24 -24
- package/src/drawer.canvasentry.js +30 -6
- package/src/drawer.js +2 -1
- 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 +120 -23
- package/src/plugin/minimap/index.js +24 -21
- package/src/plugin/regions/index.js +30 -3
- package/src/plugin/regions/region.js +47 -10
- package/src/plugin/spectrogram/index.js +101 -82
- package/src/plugin/timeline/index.js +30 -19
- package/src/util/index.js +1 -0
- package/src/util/silence-mode.js +35 -0
- package/src/wavesurfer.js +54 -23
- package/src/webaudio.js +10 -1
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.21.1",
|
|
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,25 +74,25 @@
|
|
|
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": "^
|
|
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.
|
|
95
|
-
"webpack-merge": "^5.
|
|
92
|
+
"webpack": "^5.68.0",
|
|
93
|
+
"webpack-cli": "^4.9.2",
|
|
94
|
+
"webpack-dev-server": "^4.7.4",
|
|
95
|
+
"webpack-merge": "^5.8.0"
|
|
96
96
|
},
|
|
97
97
|
"homepage": "https://wavesurfer-js.org",
|
|
98
98
|
"pre-commit": "lint-js-html",
|
|
@@ -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
|
});
|
|
@@ -342,7 +343,7 @@ export default class Drawer extends util.Observer {
|
|
|
342
343
|
destroy() {
|
|
343
344
|
this.unAll();
|
|
344
345
|
if (this.wrapper) {
|
|
345
|
-
if (this.wrapper.parentNode == this.container) {
|
|
346
|
+
if (this.wrapper.parentNode == this.container.domElement) {
|
|
346
347
|
this.container.removeChild(this.wrapper.domElement);
|
|
347
348
|
}
|
|
348
349
|
this.wrapper = null;
|
|
@@ -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,12 +1,13 @@
|
|
|
1
|
-
|
|
2
1
|
/**
|
|
3
2
|
* @typedef {Object} MarkerParams
|
|
4
3
|
* @desc The parameters used to describe a marker.
|
|
5
4
|
* @example wavesurfer.addMarker(regionParams);
|
|
6
5
|
* @property {number} time The time to set the marker at
|
|
7
|
-
* @property {?label} string
|
|
8
|
-
* @property {?color} string
|
|
6
|
+
* @property {?label} string An optional marker label
|
|
7
|
+
* @property {?color} string Background color for marker
|
|
9
8
|
* @property {?position} string "top" or "bottom", defaults to "bottom"
|
|
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
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
|
|
@@ -39,6 +40,9 @@ export default class MarkersPlugin {
|
|
|
39
40
|
/**
|
|
40
41
|
* @typedef {Object} MarkersPluginParams
|
|
41
42
|
* @property {?MarkerParams[]} markers Initial set of markers
|
|
43
|
+
* @fires MarkersPlugin#marker-click
|
|
44
|
+
* @fires MarkersPlugin#marker-drag
|
|
45
|
+
* @fires MarkersPlugin#marker-drop
|
|
42
46
|
*/
|
|
43
47
|
|
|
44
48
|
/**
|
|
@@ -76,8 +80,10 @@ export default class MarkersPlugin {
|
|
|
76
80
|
this.wavesurfer = ws;
|
|
77
81
|
this.util = ws.util;
|
|
78
82
|
this.style = this.util.style;
|
|
83
|
+
this.markerLineWidth = 1;
|
|
79
84
|
this.markerWidth = 11;
|
|
80
85
|
this.markerHeight = 22;
|
|
86
|
+
this.dragging = false;
|
|
81
87
|
|
|
82
88
|
|
|
83
89
|
this._onResize = () => {
|
|
@@ -92,6 +98,16 @@ export default class MarkersPlugin {
|
|
|
92
98
|
window.addEventListener('resize', this._onResize, true);
|
|
93
99
|
window.addEventListener('orientationchange', this._onResize, true);
|
|
94
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);
|
|
95
111
|
};
|
|
96
112
|
|
|
97
113
|
this.markers = [];
|
|
@@ -121,6 +137,13 @@ export default class MarkersPlugin {
|
|
|
121
137
|
window.removeEventListener('resize', this._onResize, true);
|
|
122
138
|
window.removeEventListener('orientationchange', this._onResize, true);
|
|
123
139
|
|
|
140
|
+
if (this.onMouseMove) {
|
|
141
|
+
window.removeEventListener('mousemove', this.onMouseMove);
|
|
142
|
+
}
|
|
143
|
+
if (this.onMouseUp) {
|
|
144
|
+
window.removeEventListener("mouseup", this.onMouseUp);
|
|
145
|
+
}
|
|
146
|
+
|
|
124
147
|
this.clear();
|
|
125
148
|
}
|
|
126
149
|
|
|
@@ -135,10 +158,11 @@ export default class MarkersPlugin {
|
|
|
135
158
|
time: params.time,
|
|
136
159
|
label: params.label,
|
|
137
160
|
color: params.color || DEFAULT_FILL_COLOR,
|
|
138
|
-
position: params.position || DEFAULT_POSITION
|
|
161
|
+
position: params.position || DEFAULT_POSITION,
|
|
162
|
+
draggable: !!params.draggable
|
|
139
163
|
};
|
|
140
164
|
|
|
141
|
-
marker.el = this._createMarkerElement(marker);
|
|
165
|
+
marker.el = this._createMarkerElement(marker, params.markerElement);
|
|
142
166
|
|
|
143
167
|
this.wrapper.appendChild(marker.el);
|
|
144
168
|
this.markers.push(marker);
|
|
@@ -190,9 +214,8 @@ export default class MarkersPlugin {
|
|
|
190
214
|
return el;
|
|
191
215
|
}
|
|
192
216
|
|
|
193
|
-
_createMarkerElement(marker) {
|
|
217
|
+
_createMarkerElement(marker, markerElement) {
|
|
194
218
|
let label = marker.label;
|
|
195
|
-
let time = marker.time;
|
|
196
219
|
|
|
197
220
|
const el = document.createElement('marker');
|
|
198
221
|
el.className = "wavesurfer-marker";
|
|
@@ -206,17 +229,22 @@ export default class MarkersPlugin {
|
|
|
206
229
|
});
|
|
207
230
|
|
|
208
231
|
const line = document.createElement('div');
|
|
232
|
+
const width = markerElement ? markerElement.width : this.markerWidth;
|
|
233
|
+
marker.offset = (width - this.markerLineWidth) / 2;
|
|
209
234
|
this.style(line, {
|
|
210
235
|
"flex-grow": 1,
|
|
211
|
-
"margin-left":
|
|
236
|
+
"margin-left": marker.offset + "px",
|
|
212
237
|
background: "black",
|
|
213
|
-
width: "
|
|
238
|
+
width: this.markerLineWidth + "px",
|
|
214
239
|
opacity: 0.1
|
|
215
240
|
});
|
|
216
241
|
el.appendChild(line);
|
|
217
242
|
|
|
218
243
|
const labelDiv = document.createElement('div');
|
|
219
|
-
const point = this._createPointerSVG(marker.color, marker.position);
|
|
244
|
+
const point = markerElement || this._createPointerSVG(marker.color, marker.position);
|
|
245
|
+
if (marker.draggable){
|
|
246
|
+
point.draggable = false;
|
|
247
|
+
}
|
|
220
248
|
labelDiv.appendChild(point);
|
|
221
249
|
|
|
222
250
|
if ( label ) {
|
|
@@ -239,30 +267,99 @@ export default class MarkersPlugin {
|
|
|
239
267
|
|
|
240
268
|
labelDiv.addEventListener("click", e => {
|
|
241
269
|
e.stopPropagation();
|
|
242
|
-
|
|
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);
|
|
277
|
+
this.wavesurfer.fireEvent("marker-click", marker, e);
|
|
243
278
|
});
|
|
244
279
|
|
|
280
|
+
if (marker.draggable) {
|
|
281
|
+
labelDiv.addEventListener("mousedown", e => {
|
|
282
|
+
this.selectedMarker = marker;
|
|
283
|
+
});
|
|
284
|
+
}
|
|
245
285
|
return el;
|
|
246
286
|
}
|
|
247
287
|
|
|
248
288
|
_updateMarkerPositions() {
|
|
249
|
-
const duration = this.wavesurfer.getDuration();
|
|
250
|
-
|
|
251
289
|
for ( let i = 0 ; i < this.markers.length; i++ ) {
|
|
252
290
|
let marker = this.markers[i];
|
|
253
|
-
|
|
254
|
-
this.wavesurfer.drawer.width /
|
|
255
|
-
this.wavesurfer.params.pixelRatio;
|
|
256
|
-
|
|
257
|
-
const positionPct = Math.min(marker.time / duration, 1);
|
|
258
|
-
const leftPx = ((elementWidth * positionPct) - (this.markerWidth / 2));
|
|
259
|
-
this.style(marker.el, {
|
|
260
|
-
"left": leftPx + "px",
|
|
261
|
-
"max-width": (elementWidth - leftPx) + "px"
|
|
262
|
-
});
|
|
291
|
+
this._updateMarkerPosition(marker);
|
|
263
292
|
}
|
|
264
293
|
}
|
|
265
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
|
+
|
|
266
363
|
/**
|
|
267
364
|
* Remove all markers
|
|
268
365
|
*/
|