wavesurfer.js 7.0.0-alpha.0 → 7.0.0-alpha.2
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/README.md +1 -1
- package/dist/event-emitter.d.ts +2 -0
- package/dist/wavesurfer.Regions.min.js +1 -0
- package/dist/wavesurfer.min.js +1 -0
- package/package.json +14 -6
- package/.eslintrc.json +0 -24
- package/.prettierrc +0 -8
- package/dist/base-plugin.js +0 -13
- package/dist/decoder.js +0 -43
- package/dist/event-emitter.js +0 -21
- package/dist/fetcher.js +0 -17
- package/dist/index.js +0 -166
- package/dist/player-webaudio.js +0 -31
- package/dist/player.js +0 -40
- package/dist/plugins/regions.js +0 -183
- package/dist/renderer.js +0 -193
- package/dist/timer.js +0 -17
- package/examples/audio.ogg +0 -0
- package/examples/bars.js +0 -19
- package/examples/basic.js +0 -8
- package/examples/gradient.js +0 -28
- package/examples/regions.js +0 -63
- package/examples/video.js +0 -19
- package/examples/webaudio.js +0 -14
- package/src/base-plugin.ts +0 -20
- package/src/decoder.ts +0 -41
- package/src/event-emitter.ts +0 -35
- package/src/fetcher.ts +0 -7
- package/src/index.ts +0 -252
- package/src/player-webaudio.ts +0 -34
- package/src/player.ts +0 -50
- package/src/plugins/regions.ts +0 -240
- package/src/renderer.ts +0 -250
- package/src/timer.ts +0 -27
- package/tsconfig.json +0 -105
- package/tutorial/index.html +0 -47
- package/tutorial/src/editor.js +0 -70
- package/tutorial/src/init.js +0 -66
- package/tutorial/src/url.js +0 -25
- package/tutorial/style.css +0 -211
- package/yarn-error.log +0 -1049
package/README.md
CHANGED
package/dist/event-emitter.d.ts
CHANGED
|
@@ -7,5 +7,7 @@ declare class EventEmitter<EventTypes extends GeneralEventTypes> {
|
|
|
7
7
|
protected emit<T extends keyof EventTypes>(eventType: T, detail?: EventTypes[T]): void;
|
|
8
8
|
/** Subscribe to an event and return a function to unsubscribe */
|
|
9
9
|
on<T extends keyof EventTypes>(eventType: T, callback: (detail: EventTypes[T]) => void): () => void;
|
|
10
|
+
/** Subscribe to an event once and return a function to unsubscribe */
|
|
11
|
+
once<T extends keyof EventTypes>(eventType: T, callback: (detail: EventTypes[T]) => void): () => void;
|
|
10
12
|
}
|
|
11
13
|
export default EventEmitter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Regions=t():e.Regions=t()}(WaveSurfer,(()=>(()=>{"use strict";var e={d:(t,i)=>{for(var n in i)e.o(i,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:i[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{default:()=>s});const i=class{constructor(){this.eventTarget=new EventTarget}emit(e,t){const i=new CustomEvent(String(e),{detail:t});this.eventTarget.dispatchEvent(i)}on(e,t){const i=e=>{e instanceof CustomEvent&&t(e.detail)},n=String(e);return this.eventTarget.addEventListener(n,i),()=>this.eventTarget.removeEventListener(n,i)}once(e,t){const i=this.on(e,((...e)=>{i(),t(...e)}));return i}},n=class extends i{constructor(e){super(),this.subscriptions=[],this.wavesurfer=e.wavesurfer,this.renderer=e.renderer}destroy(){this.subscriptions.forEach((e=>e()))}},s=class extends n{constructor(e){super(e),this.dragStart=NaN,this.regions=[],this.createdRegion=null,this.modifiedRegion=null,this.isResizingLeft=!1,this.isMoving=!1,this.handleMouseDown=e=>{this.dragStart=e.clientX-this.container.getBoundingClientRect().left},this.handleMouseMove=e=>{const t=e.clientX-this.container.getBoundingClientRect().left;if(this.modifiedRegion&&this.isMoving)return this.moveRegion(this.modifiedRegion,t-this.dragStart),void(this.dragStart=t);if(this.modifiedRegion)this.updateRegion(this.modifiedRegion,this.isResizingLeft?t:void 0,this.isResizingLeft?void 0:t);else if(!isNaN(this.dragStart)){const t=e.clientX-this.container.getBoundingClientRect().left;t-this.dragStart>=10&&(this.createdRegion?this.updateRegion(this.createdRegion,this.dragStart,t):(this.renderer.getContainer().style.pointerEvents="none",this.createdRegion=this.createRegion(this.dragStart,t)))}},this.handleMouseUp=()=>{this.createdRegion&&(this.addRegion(this.createdRegion),this.createdRegion=null),this.modifiedRegion=null,this.isMoving=!1,this.dragStart=NaN,this.renderer.getContainer().style.pointerEvents=""},this.container=this.initContainer();const t=this.wavesurfer.on("ready",(()=>{this.renderer.getContainer().appendChild(this.container),t()}));this.subscriptions.push(t),this.renderer.getContainer().addEventListener("mousedown",this.handleMouseDown),document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("mouseup",this.handleMouseUp)}destroy(){var e;this.renderer.getContainer().removeEventListener("mousedown",this.handleMouseDown),document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp,!0),null===(e=this.container)||void 0===e||e.remove(),super.destroy()}initContainer(){const e=document.createElement("div");return e.style.position="absolute",e.style.top="0",e.style.left="0",e.style.width="100%",e.style.height="100%",e.style.zIndex="3",e.style.pointerEvents="none",e}createRegionElement(e,t,i=""){const n=document.createElement("div");n.style.position="absolute",n.style.left=`${e}px`,n.style.width=t-e+"px",n.style.height="100%",n.style.backgroundColor="rgba(0, 0, 0, 0.1)",n.style.transition="background-color 0.2s ease",n.style.cursor="move",n.style.pointerEvents="all",n.title=i;const s=document.createElement("div");s.style.position="absolute",s.style.left="0",s.style.width="6px",s.style.height="100%",s.style.borderLeft="2px solid rgba(0, 0, 0, 0.5)",s.style.cursor="ew-resize",s.style.pointerEvents="all",n.appendChild(s);const o=document.createElement("div");return o.style.position="absolute",o.style.right="0",o.style.width="6px",o.style.height="100%",o.style.borderRight="2px solid rgba(0, 0, 0, 0.5)",o.style.cursor="ew-resize",o.style.pointerEvents="all",n.appendChild(o),s.addEventListener("mousedown",(e=>{e.stopPropagation(),this.modifiedRegion=this.regions.find((e=>e.element===n))||null,this.isResizingLeft=!0,this.isMoving=!1})),o.addEventListener("mousedown",(e=>{e.stopPropagation(),this.modifiedRegion=this.regions.find((e=>e.element===n))||null,this.isResizingLeft=!1,this.isMoving=!1})),n.addEventListener("mousedown",(()=>{this.modifiedRegion=this.regions.find((e=>e.element===n))||null,this.isMoving=!0})),n.addEventListener("click",(()=>{const e=this.regions.find((e=>e.element===n));e&&this.emit("region-clicked",{region:e})})),this.container.appendChild(n),n}createRegion(e,t,i=""){const n=this.wavesurfer.getDuration(),s=this.container.clientWidth;return{element:this.createRegionElement(e,t,i),start:e,end:t,startTime:e/s*n,endTime:t/s*n,title:i}}addRegion(e){this.regions.push(e),this.emit("region-created",{region:e})}updateRegion(e,t,i){null!=t&&(e.start=null!=t?t:e.start,e.element.style.left=`${e.start}px`,e.startTime=t/this.container.clientWidth*this.wavesurfer.getDuration()),null!=i&&(e.end=i,e.element.style.width=e.end-e.start+"px",e.endTime=i/this.container.clientWidth*this.wavesurfer.getDuration()),this.emit("region-updated",{region:e})}moveRegion(e,t){this.updateRegion(e,e.start+t,e.end+t)}addRegionAtTime(e,t,i=""){const n=this.wavesurfer.getDuration(),s=this.container.clientWidth,o=e/n*s,r=t/n*s,d=this.createRegion(o,r,i);return this.addRegion(d),d}setRegionColor(e,t){e.element.style.backgroundColor=t}};return t.default})()));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.WaveSurfer=e():t.WaveSurfer=e()}(this,(()=>(()=>{"use strict";var t={d:(e,i)=>{for(var n in i)t.o(i,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:i[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},e={};t.d(e,{default:()=>l});const i=class{constructor(){this.eventTarget=new EventTarget}emit(t,e){const i=new CustomEvent(String(t),{detail:e});this.eventTarget.dispatchEvent(i)}on(t,e){const i=t=>{t instanceof CustomEvent&&e(t.detail)},n=String(t);return this.eventTarget.addEventListener(n,i),()=>this.eventTarget.removeEventListener(n,i)}once(t,e){const i=this.on(t,((...t)=>{i(),e(...t)}));return i}},n=class extends i{constructor(t){super(),this.options=t;let e=null;if("string"==typeof this.options.container?e=document.querySelector(this.options.container):this.options.container instanceof HTMLElement&&(e=this.options.container),!e)throw new Error("Container not found");const i=document.createElement("div"),n=i.attachShadow({mode:"open"});n.innerHTML=`\n <style>\n :host .scroll {\n overflow-x: auto;\n overflow-y: visible;\n user-select: none;\n width: 100%;\n height: ${this.options.height}px;\n position: relative;\n }\n :host .wrapper {\n position: relative;\n width: fit-content;\n min-width: 100%;\n height: 100%;\n z-index: 2;\n }\n :host canvas {\n display: block;\n height: 100%;\n min-width: 100%;\n image-rendering: pixelated;\n }\n :host .progress {\n position: absolute;\n z-index: 2;\n top: 0;\n left: 0;\n height: 100%;\n pointer-events: none;\n clip-path: inset(100%);\n }\n :host .cursor {\n position: absolute;\n z-index: 3;\n top: 0;\n left: 0;\n height: 100%;\n border-right: 1px solid ${this.options.progressColor};\n }\n </style>\n\n <div class="scroll">\n <div class="wrapper">\n <canvas></canvas>\n <canvas class="progress"></canvas>\n <div class="cursor"></div>\n </div>\n </div>\n `,this.container=i,this.shadowRoot=n,this.mainCanvas=n.querySelector("canvas"),this.ctx=this.mainCanvas.getContext("2d",{desynchronized:!0}),this.progressCanvas=n.querySelector(".progress"),this.cursor=n.querySelector(".cursor"),e.appendChild(i),this.mainCanvas.addEventListener("click",(t=>{const e=this.mainCanvas.getBoundingClientRect(),i=(t.clientX-e.left)/e.width;this.emit("click",{relativeX:i})}))}destroy(){this.container.remove()}renderLinePeaks(t,e,i){const{ctx:n}=this;n.clearRect(0,0,e,i),n.beginPath(),n.moveTo(0,i/2);const s=t[0],r=1===t.length,o=r?s:t[1];let a=-1,h=0;for(let t=0,r=s.length;t<r;t++){const r=Math.round(t/s.length*e),o=Math.round((1-s[t])*i/2);(r!==a||o>h)&&(n.lineTo(r,o),a=r,h=o)}a=-1,h=0;for(let t=o.length-1;t>=0;t--){const s=Math.round(t/o.length*e),d=Math.round((1+o[t])*i/2);(s!==a||(r?d<-h:d>h))&&(n.lineTo(s,d),a=s,h=d)}n.strokeStyle=n.fillStyle=this.options.waveColor,n.stroke(),n.fill()}renderBarPeaks(t,e,i){var n,s;const{devicePixelRatio:r}=window,{ctx:o}=this;o.clearRect(0,0,e,i);const a=this.options.barWidth||1,h=a*r,d=(null!==(n=this.options.barGap)&&void 0!==n?n:a/2)*r,l=null!==(s=this.options.barRadius)&&void 0!==s?s:0,c=t[0],u=1===t.length,p=u?c:t[1],v=Math.floor(e/(h+d)),m=new Float32Array(v),g=new Float32Array(v),y=v/c.length,f=c.length;for(let t=0;t<f;t++){const e=Math.round(t*y);m[e]=Math.max(m[e],c[t]),g[e]=(u?Math.min:Math.max)(g[e],p[t])}o.beginPath();for(let t=0;t<v;t++){const e=Math.max(1,Math.round(m[t]*i/2)),n=Math.max(1,Math.round(Math.abs(g[t]*i)/2));o.roundRect(t*(h+d),i/2-e,h,e+n,l)}o.fillStyle=this.options.waveColor,o.fill()}render(t,e,i=this.options.minPxPerSec){const{devicePixelRatio:n}=window,s=Math.max(this.container.clientWidth*n,e*i),{height:r}=this.options;this.mainCanvas.width=s,this.mainCanvas.height=r,this.mainCanvas.style.width=Math.round(s/n)+"px",(this.options.barWidth?this.renderBarPeaks:this.renderLinePeaks).call(this,t,s,r),this.createProgressMask()}createProgressMask(){const t=this.progressCanvas.getContext("2d",{desynchronized:!0});if(!t)throw new Error("Failed to get canvas context");this.progressCanvas.width=this.mainCanvas.width,this.progressCanvas.height=this.mainCanvas.height,this.progressCanvas.style.width=this.mainCanvas.style.width,this.progressCanvas.style.height=this.mainCanvas.style.height,t.drawImage(this.mainCanvas,0,0),t.globalCompositeOperation="source-in",t.fillStyle=this.options.progressColor,t.fillRect(0,0,this.progressCanvas.width,this.progressCanvas.height)}renderProgress(t,e=!1){if(this.progressCanvas.style.clipPath=`inset(0 ${100-100*t}% 0 0)`,this.cursor.style.left=100*t+"%",e){const e=this.container.clientWidth/2,i=this.mainCanvas.clientWidth;i*t>=e&&(this.container.scrollLeft=i*t-e)}}getContainer(){return this.shadowRoot.querySelector(".scroll")}},s=class{constructor({media:t}){this.isExternalMedia=!1,t?(this.media=t,this.isExternalMedia=!0):this.media=document.createElement("audio")}on(t,e){return this.media.addEventListener(t,e),()=>this.media.removeEventListener(t,e)}destroy(){this.isExternalMedia||this.media.remove()}loadUrl(t){this.media.src=t}getCurrentTime(){return this.media.currentTime}play(){this.media.play()}pause(){this.media.pause()}isPlaying(){return this.media.currentTime>0&&!this.media.paused&&!this.media.ended}seekTo(t){this.media.currentTime=t}},r=class extends s{constructor(){super(...arguments),this.audioCtx=null,this.sourceNode=null}destroy(){var t,e;null===(t=this.sourceNode)||void 0===t||t.disconnect(),this.sourceNode=null,null===(e=this.audioCtx)||void 0===e||e.close(),this.audioCtx=null,super.destroy()}loadUrl(t){super.loadUrl(t),this.audioCtx||(this.audioCtx=new AudioContext({latencyHint:"playback"})),this.sourceNode&&this.sourceNode.disconnect(),this.sourceNode=this.audioCtx.createMediaElementSource(this.media),this.sourceNode.connect(this.audioCtx.destination)}},o=class extends i{constructor(){super(),this.unsubscribe=()=>{},this.unsubscribe=this.on("tick",(()=>{requestAnimationFrame((()=>{this.emit("tick")}))})),this.emit("tick")}destroy(){this.unsubscribe()}};var a;!function(t){t.WebAudio="WebAudio",t.MediaElement="MediaElement"}(a||(a={}));const h={height:128,waveColor:"#999",progressColor:"#555",minPxPerSec:0,backend:"MediaElement"};class d extends i{static create(t){return new d(t)}constructor(t){var e;super(),this.plugins=[],this.subscriptions=[],this.channelData=null,this.duration=0,this.options=Object.assign({},h,t),this.fetcher=new class{load(t){return e=this,i=void 0,s=function*(){return fetch(t).then((t=>t.arrayBuffer()))},new((n=void 0)||(n=Promise))((function(t,r){function o(t){try{h(s.next(t))}catch(t){r(t)}}function a(t){try{h(s.throw(t))}catch(t){r(t)}}function h(e){var i;e.done?t(e.value):(i=e.value,i instanceof n?i:new n((function(t){t(i)}))).then(o,a)}h((s=s.apply(e,i||[])).next())}));var e,i,n,s}},this.decoder=new class{constructor(){this.audioCtx=null,this.audioCtx=new AudioContext({latencyHint:"playback",sampleRate:3e3})}decode(t){return e=this,i=void 0,s=function*(){if(!this.audioCtx)throw new Error("AudioContext is not initialized");const e=yield this.audioCtx.decodeAudioData(t),i=[e.getChannelData(0)];return e.numberOfChannels>1&&i.push(e.getChannelData(1)),{duration:e.duration,channelData:i}},new((n=void 0)||(n=Promise))((function(t,r){function o(t){try{h(s.next(t))}catch(t){r(t)}}function a(t){try{h(s.throw(t))}catch(t){r(t)}}function h(e){var i;e.done?t(e.value):(i=e.value,i instanceof n?i:new n((function(t){t(i)}))).then(o,a)}h((s=s.apply(e,i||[])).next())}));var e,i,n,s}destroy(){var t;null===(t=this.audioCtx)||void 0===t||t.close(),this.audioCtx=null}},this.timer=new o,this.player=new(this.options.backend===a.WebAudio?r:s)({media:this.options.media}),this.renderer=new n({container:this.options.container,height:this.options.height,waveColor:this.options.waveColor,progressColor:this.options.progressColor,minPxPerSec:this.options.minPxPerSec,barWidth:this.options.barWidth,barGap:this.options.barGap,barRadius:this.options.barRadius}),this.initPlayerEvents(),this.initRendererEvents(),this.initTimerEvents();const i=this.options.url||(null===(e=this.options.media)||void 0===e?void 0:e.src);i&&this.load(i,this.options.channelData,this.options.duration)}initPlayerEvents(){this.subscriptions.push(this.player.on("timeupdate",(()=>{const t=this.getCurrentTime();this.renderer.renderProgress(t/this.duration,this.isPlaying()),this.emit("audioprocess",{currentTime:t})})),this.player.on("play",(()=>{this.emit("play")})),this.player.on("pause",(()=>{this.emit("pause")})),this.player.on("canplay",(()=>{this.emit("canplay")})),this.player.on("seeking",(()=>{this.emit("seek",{time:this.getCurrentTime()})})))}initRendererEvents(){this.subscriptions.push(this.renderer.on("click",(({relativeX:t})=>{const e=this.getDuration()*t;this.seekTo(e)})))}initTimerEvents(){this.subscriptions.push(this.timer.on("tick",(()=>{if(this.isPlaying()){const t=this.getCurrentTime();this.renderer.renderProgress(t/this.duration,!0),this.emit("audioprocess",{currentTime:t})}})))}destroy(){this.subscriptions.forEach((t=>t())),this.plugins.forEach((t=>t.destroy())),this.timer.destroy(),this.player.destroy(),this.decoder.destroy(),this.renderer.destroy()}load(t,e,i){return n=this,s=void 0,o=function*(){if(this.player.loadUrl(t),null==e||null==i){const n=yield this.fetcher.load(t),s=yield this.decoder.decode(n);e=s.channelData,i=s.duration}this.channelData=e,this.duration=i,this.renderer.render(this.channelData,this.duration),this.emit("ready",{duration:this.duration})},new((r=void 0)||(r=Promise))((function(t,e){function i(t){try{h(o.next(t))}catch(t){e(t)}}function a(t){try{h(o.throw(t))}catch(t){e(t)}}function h(e){var n;e.done?t(e.value):(n=e.value,n instanceof r?n:new r((function(t){t(n)}))).then(i,a)}h((o=o.apply(n,s||[])).next())}));var n,s,r,o}zoom(t){if(null==this.channelData||null==this.duration)throw new Error("No audio loaded");this.renderer.render(this.channelData,this.duration,t),this.renderer.renderProgress(this.getCurrentTime()/this.duration,!0)}play(){this.player.play()}pause(){this.player.pause()}seekTo(t){this.player.seekTo(t)}isPlaying(){return this.player.isPlaying()}getDuration(){return this.duration}getCurrentTime(){return this.player.getCurrentTime()}registerPlugin(t){const e=new t({wavesurfer:this,renderer:this.renderer});return this.plugins.push(e),e}}const l=d;return e.default})()));
|
package/package.json
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wavesurfer.js",
|
|
3
|
-
"version": "7.0.0-alpha.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "7.0.0-alpha.2",
|
|
4
|
+
"description": "wavesurfer.js is an audio library that draws waveforms and plays audio in the browser.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"files": ["dist/"],
|
|
7
8
|
"scripts": {
|
|
8
|
-
"build": "tsc",
|
|
9
|
+
"build:dev": "tsc -w",
|
|
10
|
+
"build:umd": "webpack && webpack --config webpack.config.plugins.js",
|
|
11
|
+
"prepublishOnly": "npm run build:umd",
|
|
9
12
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
13
|
"lint": "eslint --ext .ts src --fix",
|
|
11
14
|
"prettier": "prettier -w src",
|
|
12
|
-
"docs": "npx typedoc src/index.ts"
|
|
15
|
+
"docs": "npx typedoc src/index.ts",
|
|
16
|
+
"serve": "python3 -m http.server --cgi 8080"
|
|
13
17
|
},
|
|
14
18
|
"author": "katspaugh <katspaugh@gmail.com>",
|
|
15
19
|
"license": "ISC",
|
|
@@ -20,7 +24,11 @@
|
|
|
20
24
|
"eslint-config-prettier": "^8.7.0",
|
|
21
25
|
"eslint-plugin-prettier": "^4.2.1",
|
|
22
26
|
"prettier": "^2.8.4",
|
|
27
|
+
"ts-loader": "^9.4.2",
|
|
23
28
|
"typedoc": "^0.23.26",
|
|
24
|
-
"typescript": "^4.9.5"
|
|
25
|
-
|
|
29
|
+
"typescript": "^4.9.5",
|
|
30
|
+
"webpack": "^5.76.1",
|
|
31
|
+
"webpack-cli": "^5.0.1"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {}
|
|
26
34
|
}
|
package/.eslintrc.json
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"env": {
|
|
3
|
-
"browser": true,
|
|
4
|
-
"es2021": true
|
|
5
|
-
},
|
|
6
|
-
"extends": [
|
|
7
|
-
"eslint:recommended",
|
|
8
|
-
"plugin:@typescript-eslint/recommended",
|
|
9
|
-
"prettier",
|
|
10
|
-
"plugin:prettier/recommended"
|
|
11
|
-
],
|
|
12
|
-
"overrides": [
|
|
13
|
-
],
|
|
14
|
-
"parser": "@typescript-eslint/parser",
|
|
15
|
-
"parserOptions": {
|
|
16
|
-
"ecmaVersion": "latest",
|
|
17
|
-
"sourceType": "module"
|
|
18
|
-
},
|
|
19
|
-
"plugins": [
|
|
20
|
-
"@typescript-eslint"
|
|
21
|
-
],
|
|
22
|
-
"rules": {
|
|
23
|
-
}
|
|
24
|
-
}
|
package/.prettierrc
DELETED
package/dist/base-plugin.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import EventEmitter from './event-emitter.js';
|
|
2
|
-
export class BasePlugin extends EventEmitter {
|
|
3
|
-
constructor(params) {
|
|
4
|
-
super();
|
|
5
|
-
this.subscriptions = [];
|
|
6
|
-
this.wavesurfer = params.wavesurfer;
|
|
7
|
-
this.renderer = params.renderer;
|
|
8
|
-
}
|
|
9
|
-
destroy() {
|
|
10
|
-
this.subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
export default BasePlugin;
|
package/dist/decoder.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
// Web Audio decodeAudioData with a minimum allowed sample rate
|
|
11
|
-
const SAMPLE_RATE = 3000;
|
|
12
|
-
class Decoder {
|
|
13
|
-
constructor() {
|
|
14
|
-
this.audioCtx = null;
|
|
15
|
-
this.audioCtx = new (window.AudioContext ||
|
|
16
|
-
window.webkitAudioContext)({
|
|
17
|
-
latencyHint: 'playback',
|
|
18
|
-
sampleRate: SAMPLE_RATE,
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
decode(audioData) {
|
|
22
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
23
|
-
if (!this.audioCtx) {
|
|
24
|
-
throw new Error('AudioContext is not initialized');
|
|
25
|
-
}
|
|
26
|
-
const buffer = yield this.audioCtx.decodeAudioData(audioData);
|
|
27
|
-
const channelData = [buffer.getChannelData(0)];
|
|
28
|
-
if (buffer.numberOfChannels > 1) {
|
|
29
|
-
channelData.push(buffer.getChannelData(1));
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
duration: buffer.duration,
|
|
33
|
-
channelData,
|
|
34
|
-
};
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
destroy() {
|
|
38
|
-
var _a;
|
|
39
|
-
(_a = this.audioCtx) === null || _a === void 0 ? void 0 : _a.close();
|
|
40
|
-
this.audioCtx = null;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
export default Decoder;
|
package/dist/event-emitter.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
class EventEmitter {
|
|
2
|
-
constructor() {
|
|
3
|
-
this.eventTarget = new EventTarget();
|
|
4
|
-
}
|
|
5
|
-
emit(eventType, detail) {
|
|
6
|
-
const e = new CustomEvent(String(eventType), { detail });
|
|
7
|
-
this.eventTarget.dispatchEvent(e);
|
|
8
|
-
}
|
|
9
|
-
/** Subscribe to an event and return a function to unsubscribe */
|
|
10
|
-
on(eventType, callback) {
|
|
11
|
-
const handler = (e) => {
|
|
12
|
-
if (e instanceof CustomEvent) {
|
|
13
|
-
callback(e.detail);
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
const eventName = String(eventType);
|
|
17
|
-
this.eventTarget.addEventListener(eventName, handler);
|
|
18
|
-
return () => this.eventTarget.removeEventListener(eventName, handler);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
export default EventEmitter;
|
package/dist/fetcher.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
class Fetcher {
|
|
11
|
-
load(url) {
|
|
12
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
13
|
-
return fetch(url).then((response) => response.arrayBuffer());
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
export default Fetcher;
|
package/dist/index.js
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import Fetcher from './fetcher.js';
|
|
11
|
-
import Decoder from './decoder.js';
|
|
12
|
-
import Renderer from './renderer.js';
|
|
13
|
-
import Player from './player.js';
|
|
14
|
-
import WebAudioPlayer from './player-webaudio.js';
|
|
15
|
-
import EventEmitter from './event-emitter.js';
|
|
16
|
-
import Timer from './timer.js';
|
|
17
|
-
export var PlayerType;
|
|
18
|
-
(function (PlayerType) {
|
|
19
|
-
PlayerType["WebAudio"] = "WebAudio";
|
|
20
|
-
PlayerType["MediaElement"] = "MediaElement";
|
|
21
|
-
})(PlayerType || (PlayerType = {}));
|
|
22
|
-
const defaultOptions = {
|
|
23
|
-
height: 128,
|
|
24
|
-
waveColor: '#999',
|
|
25
|
-
progressColor: '#555',
|
|
26
|
-
minPxPerSec: 0,
|
|
27
|
-
backend: 'MediaElement',
|
|
28
|
-
};
|
|
29
|
-
export class WaveSurfer extends EventEmitter {
|
|
30
|
-
/** Create a new WaveSurfer instance */
|
|
31
|
-
static create(options) {
|
|
32
|
-
return new WaveSurfer(options);
|
|
33
|
-
}
|
|
34
|
-
/** Create a new WaveSurfer instance */
|
|
35
|
-
constructor(options) {
|
|
36
|
-
var _a;
|
|
37
|
-
super();
|
|
38
|
-
this.plugins = [];
|
|
39
|
-
this.subscriptions = [];
|
|
40
|
-
this.channelData = null;
|
|
41
|
-
this.duration = 0;
|
|
42
|
-
this.options = Object.assign({}, defaultOptions, options);
|
|
43
|
-
this.fetcher = new Fetcher();
|
|
44
|
-
this.decoder = new Decoder();
|
|
45
|
-
this.timer = new Timer();
|
|
46
|
-
this.player = new (this.options.backend === PlayerType.WebAudio ? WebAudioPlayer : Player)({
|
|
47
|
-
media: this.options.media,
|
|
48
|
-
});
|
|
49
|
-
this.renderer = new Renderer({
|
|
50
|
-
container: this.options.container,
|
|
51
|
-
height: this.options.height,
|
|
52
|
-
waveColor: this.options.waveColor,
|
|
53
|
-
progressColor: this.options.progressColor,
|
|
54
|
-
minPxPerSec: this.options.minPxPerSec,
|
|
55
|
-
barWidth: this.options.barWidth,
|
|
56
|
-
barGap: this.options.barGap,
|
|
57
|
-
barRadius: this.options.barRadius,
|
|
58
|
-
});
|
|
59
|
-
this.initPlayerEvents();
|
|
60
|
-
this.initRendererEvents();
|
|
61
|
-
this.initTimerEvents();
|
|
62
|
-
const url = this.options.url || ((_a = this.options.media) === null || _a === void 0 ? void 0 : _a.src);
|
|
63
|
-
if (url) {
|
|
64
|
-
this.load(url, this.options.channelData, this.options.duration);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
initPlayerEvents() {
|
|
68
|
-
this.subscriptions.push(this.player.on('timeupdate', () => {
|
|
69
|
-
const currentTime = this.getCurrentTime();
|
|
70
|
-
this.renderer.renderProgress(currentTime / this.duration, this.isPlaying());
|
|
71
|
-
this.emit('audioprocess', { currentTime });
|
|
72
|
-
}), this.player.on('play', () => {
|
|
73
|
-
this.emit('play');
|
|
74
|
-
}), this.player.on('pause', () => {
|
|
75
|
-
this.emit('pause');
|
|
76
|
-
}), this.player.on('canplay', () => {
|
|
77
|
-
this.emit('canplay');
|
|
78
|
-
}), this.player.on('seeking', () => {
|
|
79
|
-
this.emit('seek', { time: this.getCurrentTime() });
|
|
80
|
-
}));
|
|
81
|
-
}
|
|
82
|
-
initRendererEvents() {
|
|
83
|
-
// Seek on click
|
|
84
|
-
this.subscriptions.push(this.renderer.on('click', ({ relativeX }) => {
|
|
85
|
-
const time = this.getDuration() * relativeX;
|
|
86
|
-
this.seekTo(time);
|
|
87
|
-
}));
|
|
88
|
-
}
|
|
89
|
-
initTimerEvents() {
|
|
90
|
-
// The timer fires every 16ms for a smooth progress animation
|
|
91
|
-
this.subscriptions.push(this.timer.on('tick', () => {
|
|
92
|
-
if (this.isPlaying()) {
|
|
93
|
-
const currentTime = this.getCurrentTime();
|
|
94
|
-
this.renderer.renderProgress(currentTime / this.duration, true);
|
|
95
|
-
this.emit('audioprocess', { currentTime });
|
|
96
|
-
}
|
|
97
|
-
}));
|
|
98
|
-
}
|
|
99
|
-
/** Unmount wavesurfer */
|
|
100
|
-
destroy() {
|
|
101
|
-
this.subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
102
|
-
this.plugins.forEach((plugin) => plugin.destroy());
|
|
103
|
-
this.timer.destroy();
|
|
104
|
-
this.player.destroy();
|
|
105
|
-
this.decoder.destroy();
|
|
106
|
-
this.renderer.destroy();
|
|
107
|
-
}
|
|
108
|
-
/** Load an audio file by URL */
|
|
109
|
-
load(url, channelData, duration) {
|
|
110
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
111
|
-
this.player.loadUrl(url);
|
|
112
|
-
// Fetch and decode the audio of no pre-computed audio data is provided
|
|
113
|
-
if (channelData == null || duration == null) {
|
|
114
|
-
const audio = yield this.fetcher.load(url);
|
|
115
|
-
const data = yield this.decoder.decode(audio);
|
|
116
|
-
channelData = data.channelData;
|
|
117
|
-
duration = data.duration;
|
|
118
|
-
}
|
|
119
|
-
this.channelData = channelData;
|
|
120
|
-
this.duration = duration;
|
|
121
|
-
this.renderer.render(this.channelData, this.duration);
|
|
122
|
-
this.emit('ready', { duration: this.duration });
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
/** Zoom in or out */
|
|
126
|
-
zoom(minPxPerSec) {
|
|
127
|
-
if (this.channelData == null || this.duration == null) {
|
|
128
|
-
throw new Error('No audio loaded');
|
|
129
|
-
}
|
|
130
|
-
this.renderer.render(this.channelData, this.duration, minPxPerSec);
|
|
131
|
-
}
|
|
132
|
-
/** Start playing the audio */
|
|
133
|
-
play() {
|
|
134
|
-
this.player.play();
|
|
135
|
-
}
|
|
136
|
-
/** Pause the audio */
|
|
137
|
-
pause() {
|
|
138
|
-
this.player.pause();
|
|
139
|
-
}
|
|
140
|
-
/** Skip to a time position in seconds */
|
|
141
|
-
seekTo(time) {
|
|
142
|
-
this.player.seekTo(time);
|
|
143
|
-
}
|
|
144
|
-
/** Check if the audio is playing */
|
|
145
|
-
isPlaying() {
|
|
146
|
-
return this.player.isPlaying();
|
|
147
|
-
}
|
|
148
|
-
/** Get the duration of the audio in seconds */
|
|
149
|
-
getDuration() {
|
|
150
|
-
return this.duration;
|
|
151
|
-
}
|
|
152
|
-
/** Get the current audio position in seconds */
|
|
153
|
-
getCurrentTime() {
|
|
154
|
-
return this.player.getCurrentTime();
|
|
155
|
-
}
|
|
156
|
-
/** Register and initialize a plugin */
|
|
157
|
-
registerPlugin(CustomPlugin) {
|
|
158
|
-
const plugin = new CustomPlugin({
|
|
159
|
-
wavesurfer: this,
|
|
160
|
-
renderer: this.renderer,
|
|
161
|
-
});
|
|
162
|
-
this.plugins.push(plugin);
|
|
163
|
-
return plugin;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
export default WaveSurfer;
|
package/dist/player-webaudio.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import Player from './player.js';
|
|
2
|
-
class WebAudioPlayer extends Player {
|
|
3
|
-
constructor() {
|
|
4
|
-
super(...arguments);
|
|
5
|
-
this.audioCtx = null;
|
|
6
|
-
this.sourceNode = null;
|
|
7
|
-
}
|
|
8
|
-
destroy() {
|
|
9
|
-
var _a, _b;
|
|
10
|
-
(_a = this.sourceNode) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
11
|
-
this.sourceNode = null;
|
|
12
|
-
(_b = this.audioCtx) === null || _b === void 0 ? void 0 : _b.close();
|
|
13
|
-
this.audioCtx = null;
|
|
14
|
-
super.destroy();
|
|
15
|
-
}
|
|
16
|
-
loadUrl(url) {
|
|
17
|
-
super.loadUrl(url);
|
|
18
|
-
if (!this.audioCtx) {
|
|
19
|
-
this.audioCtx = new (window.AudioContext ||
|
|
20
|
-
window.webkitAudioContext)({
|
|
21
|
-
latencyHint: 'playback',
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
if (this.sourceNode) {
|
|
25
|
-
this.sourceNode.disconnect();
|
|
26
|
-
}
|
|
27
|
-
this.sourceNode = this.audioCtx.createMediaElementSource(this.media);
|
|
28
|
-
this.sourceNode.connect(this.audioCtx.destination);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
export default WebAudioPlayer;
|
package/dist/player.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
class Player {
|
|
2
|
-
constructor({ media }) {
|
|
3
|
-
this.isExternalMedia = false;
|
|
4
|
-
if (media) {
|
|
5
|
-
this.media = media;
|
|
6
|
-
this.isExternalMedia = true;
|
|
7
|
-
}
|
|
8
|
-
else {
|
|
9
|
-
this.media = document.createElement('audio');
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
on(event, callback) {
|
|
13
|
-
this.media.addEventListener(event, callback);
|
|
14
|
-
return () => this.media.removeEventListener(event, callback);
|
|
15
|
-
}
|
|
16
|
-
destroy() {
|
|
17
|
-
if (!this.isExternalMedia) {
|
|
18
|
-
this.media.remove();
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
loadUrl(src) {
|
|
22
|
-
this.media.src = src;
|
|
23
|
-
}
|
|
24
|
-
getCurrentTime() {
|
|
25
|
-
return this.media.currentTime;
|
|
26
|
-
}
|
|
27
|
-
play() {
|
|
28
|
-
this.media.play();
|
|
29
|
-
}
|
|
30
|
-
pause() {
|
|
31
|
-
this.media.pause();
|
|
32
|
-
}
|
|
33
|
-
isPlaying() {
|
|
34
|
-
return this.media.currentTime > 0 && !this.media.paused && !this.media.ended;
|
|
35
|
-
}
|
|
36
|
-
seekTo(time) {
|
|
37
|
-
this.media.currentTime = time;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
export default Player;
|
package/dist/plugins/regions.js
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import BasePlugin from '../base-plugin.js';
|
|
2
|
-
const MIN_WIDTH = 10;
|
|
3
|
-
class RegionsPlugin extends BasePlugin {
|
|
4
|
-
/** Create an instance of RegionsPlugin */
|
|
5
|
-
constructor(params) {
|
|
6
|
-
super(params);
|
|
7
|
-
this.dragStart = NaN;
|
|
8
|
-
this.regions = [];
|
|
9
|
-
this.createdRegion = null;
|
|
10
|
-
this.modifiedRegion = null;
|
|
11
|
-
this.isResizingLeft = false;
|
|
12
|
-
this.isMoving = false;
|
|
13
|
-
this.handleMouseDown = (e) => {
|
|
14
|
-
this.dragStart = e.clientX - this.container.getBoundingClientRect().left;
|
|
15
|
-
};
|
|
16
|
-
this.handleMouseMove = (e) => {
|
|
17
|
-
const dragEnd = e.clientX - this.container.getBoundingClientRect().left;
|
|
18
|
-
if (this.modifiedRegion && this.isMoving) {
|
|
19
|
-
this.moveRegion(this.modifiedRegion, dragEnd - this.dragStart);
|
|
20
|
-
this.dragStart = dragEnd;
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
if (this.modifiedRegion) {
|
|
24
|
-
this.updateRegion(this.modifiedRegion, this.isResizingLeft ? dragEnd : undefined, this.isResizingLeft ? undefined : dragEnd);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (!isNaN(this.dragStart)) {
|
|
28
|
-
const dragEnd = e.clientX - this.container.getBoundingClientRect().left;
|
|
29
|
-
if (dragEnd - this.dragStart >= MIN_WIDTH) {
|
|
30
|
-
if (!this.createdRegion) {
|
|
31
|
-
this.renderer.getContainer().style.pointerEvents = 'none';
|
|
32
|
-
this.createdRegion = this.createRegion(this.dragStart, dragEnd);
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
this.updateRegion(this.createdRegion, this.dragStart, dragEnd);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
this.handleMouseUp = () => {
|
|
41
|
-
if (this.createdRegion) {
|
|
42
|
-
this.addRegion(this.createdRegion);
|
|
43
|
-
this.createdRegion = null;
|
|
44
|
-
}
|
|
45
|
-
this.modifiedRegion = null;
|
|
46
|
-
this.isMoving = false;
|
|
47
|
-
this.dragStart = NaN;
|
|
48
|
-
this.renderer.getContainer().style.pointerEvents = '';
|
|
49
|
-
};
|
|
50
|
-
this.container = this.initContainer();
|
|
51
|
-
const unsubscribeReady = this.wavesurfer.on('ready', () => {
|
|
52
|
-
const wrapper = this.renderer.getContainer();
|
|
53
|
-
wrapper.appendChild(this.container);
|
|
54
|
-
unsubscribeReady();
|
|
55
|
-
});
|
|
56
|
-
this.subscriptions.push(unsubscribeReady);
|
|
57
|
-
const wsContainer = this.renderer.getContainer();
|
|
58
|
-
wsContainer.addEventListener('mousedown', this.handleMouseDown);
|
|
59
|
-
document.addEventListener('mousemove', this.handleMouseMove);
|
|
60
|
-
document.addEventListener('mouseup', this.handleMouseUp);
|
|
61
|
-
}
|
|
62
|
-
/** Unmounts the regions */
|
|
63
|
-
destroy() {
|
|
64
|
-
var _a;
|
|
65
|
-
this.renderer.getContainer().removeEventListener('mousedown', this.handleMouseDown);
|
|
66
|
-
document.removeEventListener('mousemove', this.handleMouseMove);
|
|
67
|
-
document.removeEventListener('mouseup', this.handleMouseUp, true);
|
|
68
|
-
(_a = this.container) === null || _a === void 0 ? void 0 : _a.remove();
|
|
69
|
-
super.destroy();
|
|
70
|
-
}
|
|
71
|
-
initContainer() {
|
|
72
|
-
const div = document.createElement('div');
|
|
73
|
-
div.style.position = 'absolute';
|
|
74
|
-
div.style.top = '0';
|
|
75
|
-
div.style.left = '0';
|
|
76
|
-
div.style.width = '100%';
|
|
77
|
-
div.style.height = '100%';
|
|
78
|
-
div.style.zIndex = '3';
|
|
79
|
-
div.style.pointerEvents = 'none';
|
|
80
|
-
return div;
|
|
81
|
-
}
|
|
82
|
-
createRegionElement(start, end, title = '') {
|
|
83
|
-
const el = document.createElement('div');
|
|
84
|
-
el.style.position = 'absolute';
|
|
85
|
-
el.style.left = `${start}px`;
|
|
86
|
-
el.style.width = `${end - start}px`;
|
|
87
|
-
el.style.height = '100%';
|
|
88
|
-
el.style.backgroundColor = 'rgba(0, 0, 0, 0.1)';
|
|
89
|
-
el.style.transition = 'background-color 0.2s ease';
|
|
90
|
-
el.style.cursor = 'move';
|
|
91
|
-
el.style.pointerEvents = 'all';
|
|
92
|
-
el.title = title;
|
|
93
|
-
const leftHandle = document.createElement('div');
|
|
94
|
-
leftHandle.style.position = 'absolute';
|
|
95
|
-
leftHandle.style.left = '0';
|
|
96
|
-
leftHandle.style.width = '6px';
|
|
97
|
-
leftHandle.style.height = '100%';
|
|
98
|
-
leftHandle.style.borderLeft = '2px solid rgba(0, 0, 0, 0.5)';
|
|
99
|
-
leftHandle.style.cursor = 'ew-resize';
|
|
100
|
-
leftHandle.style.pointerEvents = 'all';
|
|
101
|
-
el.appendChild(leftHandle);
|
|
102
|
-
const rightHandle = document.createElement('div');
|
|
103
|
-
rightHandle.style.position = 'absolute';
|
|
104
|
-
rightHandle.style.right = '0';
|
|
105
|
-
rightHandle.style.width = '6px';
|
|
106
|
-
rightHandle.style.height = '100%';
|
|
107
|
-
rightHandle.style.borderRight = '2px solid rgba(0, 0, 0, 0.5)';
|
|
108
|
-
rightHandle.style.cursor = 'ew-resize';
|
|
109
|
-
rightHandle.style.pointerEvents = 'all';
|
|
110
|
-
el.appendChild(rightHandle);
|
|
111
|
-
leftHandle.addEventListener('mousedown', (e) => {
|
|
112
|
-
e.stopPropagation();
|
|
113
|
-
this.modifiedRegion = this.regions.find((r) => r.element === el) || null;
|
|
114
|
-
this.isResizingLeft = true;
|
|
115
|
-
this.isMoving = false;
|
|
116
|
-
});
|
|
117
|
-
rightHandle.addEventListener('mousedown', (e) => {
|
|
118
|
-
e.stopPropagation();
|
|
119
|
-
this.modifiedRegion = this.regions.find((r) => r.element === el) || null;
|
|
120
|
-
this.isResizingLeft = false;
|
|
121
|
-
this.isMoving = false;
|
|
122
|
-
});
|
|
123
|
-
el.addEventListener('mousedown', () => {
|
|
124
|
-
this.modifiedRegion = this.regions.find((r) => r.element === el) || null;
|
|
125
|
-
this.isMoving = true;
|
|
126
|
-
});
|
|
127
|
-
el.addEventListener('click', () => {
|
|
128
|
-
const region = this.regions.find((r) => r.element === el);
|
|
129
|
-
if (region) {
|
|
130
|
-
this.emit('region-clicked', { region });
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
this.container.appendChild(el);
|
|
134
|
-
return el;
|
|
135
|
-
}
|
|
136
|
-
createRegion(start, end, title = '') {
|
|
137
|
-
const duration = this.wavesurfer.getDuration();
|
|
138
|
-
const width = this.container.clientWidth;
|
|
139
|
-
return {
|
|
140
|
-
element: this.createRegionElement(start, end, title),
|
|
141
|
-
start,
|
|
142
|
-
end,
|
|
143
|
-
startTime: (start / width) * duration,
|
|
144
|
-
endTime: (end / width) * duration,
|
|
145
|
-
title,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
addRegion(region) {
|
|
149
|
-
this.regions.push(region);
|
|
150
|
-
this.emit('region-created', { region });
|
|
151
|
-
}
|
|
152
|
-
updateRegion(region, start, end) {
|
|
153
|
-
if (start != null) {
|
|
154
|
-
region.start = start !== null && start !== void 0 ? start : region.start;
|
|
155
|
-
region.element.style.left = `${region.start}px`;
|
|
156
|
-
region.startTime = (start / this.container.clientWidth) * this.wavesurfer.getDuration();
|
|
157
|
-
}
|
|
158
|
-
if (end != null) {
|
|
159
|
-
region.end = end;
|
|
160
|
-
region.element.style.width = `${region.end - region.start}px`;
|
|
161
|
-
region.endTime = (end / this.container.clientWidth) * this.wavesurfer.getDuration();
|
|
162
|
-
}
|
|
163
|
-
this.emit('region-updated', { region });
|
|
164
|
-
}
|
|
165
|
-
moveRegion(region, delta) {
|
|
166
|
-
this.updateRegion(region, region.start + delta, region.end + delta);
|
|
167
|
-
}
|
|
168
|
-
/** Create a region at a given start and end time, with an optional title */
|
|
169
|
-
addRegionAtTime(startTime, endTime, title = '') {
|
|
170
|
-
const duration = this.wavesurfer.getDuration();
|
|
171
|
-
const width = this.container.clientWidth;
|
|
172
|
-
const start = (startTime / duration) * width;
|
|
173
|
-
const end = (endTime / duration) * width;
|
|
174
|
-
const region = this.createRegion(start, end, title);
|
|
175
|
-
this.addRegion(region);
|
|
176
|
-
return region;
|
|
177
|
-
}
|
|
178
|
-
/** Set the background color of a region */
|
|
179
|
-
setRegionColor(region, color) {
|
|
180
|
-
region.element.style.backgroundColor = color;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
export default RegionsPlugin;
|