-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathambient.min.js
1 lines (1 loc) · 4.89 KB
/
ambient.min.js
1
class Ambient{constructor(t,e={}){if(!t)throw new Error("Container argument is required");if(this.container="string"==typeof t?document.querySelector(t):t,!this.container)throw new Error("Container element not found");if(this.options=Object.assign({vtt:null,framerate:20},e),this.video=this.container.querySelector("video"),!this.video)throw new Error("No video element found inside the container");this.canvas=null,this.wrapper=null,this._vttCues=null,this._spriteCache=new Map,this.activeCanvases=[],this.options.vtt&&this._loadVtt(this.options.vtt)}mount(){if(this.video){if(this.canvas||this.wrapper)return this;try{return this.container.classList.add("cinematics-container"),this.video.classList.add("cinematics-visible"),this.canvas=document.createElement("canvas"),this.options.vtt?(this.wrapper=document.createElement("div"),this.wrapper.className="cinematics-wrapper",this._resizeCanvas(!0),this.wrapper.appendChild(this.canvas),this.container.appendChild(this.wrapper),this._setupVttDrawing()):(this.canvas.className="cinematics-glow",this._resizeCanvas(!1),this.container.appendChild(this.canvas),this._setupLiveDrawing()),this}catch(t){throw this.unmount(),t}}}unmount(){this.canvas&&!this.options.vtt&&this.canvas.parentNode===this.container&&this.container.removeChild(this.canvas),this.wrapper&&this.wrapper.parentNode===this.container&&this.container.removeChild(this.wrapper),this.container.classList.remove("cinematics-container"),this.video.classList.remove("cinematics-visible"),this.video&&"function"==typeof this.video.__acCleanup&&(this.video.__acCleanup(),delete this.video.__acCleanup),this.canvas=null,this.wrapper=null,this.activeCanvases=[]}_resizeCanvas(t){const e=()=>{if(this.canvas&&this.video&&(this.canvas.width=this.video.clientWidth,this.canvas.height=this.video.clientHeight,t&&this.activeCanvases.length>2))for(;this.activeCanvases.length>2;){const t=this.activeCanvases.shift();t&&t.parentNode===this.wrapper&&this.wrapper.removeChild(t)}};e(),this.video.addEventListener("resize",e),this.video.__acCleanup=()=>{this.video.removeEventListener("resize",e)}}_setupLiveDrawing(){const t=this.canvas.getContext("2d",{willReadFrequently:!0});let e=null,i=0;const s=1e3/this.options.framerate,a=()=>{const e=performance.now();if(!(e-i<s)){i=e,this.canvas.width=this.video.clientWidth,this.canvas.height=this.video.clientHeight;try{t.drawImage(this.video,0,0,this.canvas.width,this.canvas.height)}catch(t){}}},n=()=>{a(),e=window.requestAnimationFrame(n)},r=()=>{e&&(window.cancelAnimationFrame(e),e=null)},h=()=>a(),o=()=>a(),d=()=>n(),c=()=>r(),v=()=>r();this.video.addEventListener("loadeddata",h),this.video.addEventListener("seeked",o),this.video.addEventListener("play",d),this.video.addEventListener("pause",c),this.video.addEventListener("ended",v);const p=this.video.__acCleanup||(()=>{});this.video.__acCleanup=()=>{p(),this.video.removeEventListener("loadeddata",h),this.video.removeEventListener("seeked",o),this.video.removeEventListener("play",d),this.video.removeEventListener("pause",c),this.video.removeEventListener("ended",v),r()}}_setupVttDrawing(){let t=null;this.activeCanvases=[this.canvas];const e=()=>{if(!this._vttCues)return;const e=this.video.currentTime,i=this._vttCues.find((t=>e>=t.start&&e<t.end));if(!i)return;if(t&&t.start===i.start&&t.end===i.end)return;t=i;let s=this._spriteCache.get(i.src);s?s.complete&&s.naturalWidth>0&&this._drawSpriteFrame(s,i):(s=new Image,s.src=i.src,this._spriteCache.set(i.src,s),s.onload=()=>this._drawSpriteFrame(s,i))},i=()=>requestAnimationFrame(e),s=()=>e();this.video.addEventListener("timeupdate",i),this.video.addEventListener("loadeddata",s);const a=this.video.__acCleanup||(()=>{});this.video.__acCleanup=()=>{a(),this.video.removeEventListener("timeupdate",i),this.video.removeEventListener("loadeddata",s)}}_drawSpriteFrame(t,e){let i=this.canvas.cloneNode(!0);const s=i.getContext("2d");for(i.width=this.video.clientWidth,i.height=this.video.clientHeight,s.clearRect(0,0,i.width,i.height),s.drawImage(t,e.x,e.y,e.w,e.h,0,0,i.width,i.height),this.wrapper.appendChild(i);this.wrapper.childElementCount>2;)this.wrapper.removeChild(this.wrapper.firstElementChild)}async _loadVtt(t){try{const e=await fetch(t);if(!e.ok)throw new Error(`HTTP error! status: ${e.status}`);const i=await e.text();this._vttCues=this._parseVtt(i,t)}catch(t){}}_parseVtt(t,e){const i=e.substring(0,e.lastIndexOf("/"));return t.split("\n").reduce(((t,e,s,a)=>{if(e=e.trim(),0===s&&e.toUpperCase().startsWith("WEBVTT"))return t;if(e.includes("--\x3e")){const[n,r]=e.split("--\x3e").map((t=>t.trim())),h=this._parseTime(n),o=this._parseTime(r),d=a[s+1]?.trim();if(d){const[e,s]=d.split("#");let a=0,n=0,r=0,c=0;s&&s.startsWith("xywh=")&&([a,n,r,c]=s.replace("xywh=","").split(",").map((t=>parseInt(t,10))));const v=e.includes("/")?e:`${i}/${e}`;t.push({start:h,end:o,src:v,x:a,y:n,w:r,h:c})}}return t}),[])}_parseTime(t){const e=t.split(":");if(3===e.length){return 3600*parseFloat(e[0])+60*parseFloat(e[1])+parseFloat(e[2])}return 0}}