artplayer-plugin-danmuku
Advanced tools
Comparing version 5.0.1 to 5.1.0
/*! | ||
* artplayer-plugin-danmuku.js v5.0.1 | ||
* artplayer-plugin-danmuku.js v5.1.0 | ||
* Github: https://github.com/zhw2590582/ArtPlayer | ||
* (c) 2017-2023 Harvey Zack | ||
* (c) 2017-2024 Harvey Zack | ||
* Released under the MIT License. | ||
*/ | ||
!function(t,e,n,i,r){var a="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof a[i]&&a[i],o=s.cache||{},l="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function u(e,n){if(!o[e]){if(!t[e]){var r="function"==typeof a[i]&&a[i];if(!n&&r)return r(e,!0);if(s)return s(e,!0);if(l&&"string"==typeof e)return l(e);var d=new Error("Cannot find module '"+e+"'");throw d.code="MODULE_NOT_FOUND",d}p.resolve=function(n){var i=t[e][1][n];return null!=i?i:n},p.cache={};var m=o[e]=new u.Module(e);t[e][0].call(m.exports,p,m,m.exports,this)}return o[e].exports;function p(t){var e=p.resolve(t);return!1===e?{}:u(e)}}u.isParcelRequire=!0,u.Module=function(t){this.id=t,this.bundle=u,this.exports={}},u.modules=t,u.cache=o,u.parent=s,u.register=function(e,n){t[e]=[function(t,e){e.exports=n},{}]},Object.defineProperty(u,"root",{get:function(){return a[i]}}),a[i]=u;for(var d=0;d<e.length;d++)u(e[d]);if(n){var m=u(n);"object"==typeof exports&&"undefined"!=typeof module?module.exports=m:"function"==typeof define&&define.amd&&define((function(){return m}))}}({bgm6t:[function(t,e,n){var i=t("@parcel/transformer-js/src/esmodule-helpers.js");i.defineInteropFlag(n);var r=t("./danmuku"),a=i.interopDefault(r),s=t("./setting"),o=i.interopDefault(s),l=t("./heatmap"),u=i.interopDefault(l);function d(t){return e=>{!function(t){const{version:e,utils:{errorHandle:n}}=t.constructor,i=e.split(".").map(Number);n(i[0]+i[1]/100>=5,`Artplayer.js@${e} 不兼容该弹幕库,请更新到 Artplayer.js@5.x.x 版本以上`)}(e);const n=new(0,a.default)(e,t);return(0,o.default)(e,n),t.heatmap&&!e.option.isLive&&(0,u.default)(e,n,t.heatmap),{name:"artplayerPluginDanmuku",emit:n.emit.bind(n),load:n.load.bind(n),config:n.config.bind(n),hide:n.hide.bind(n),show:n.show.bind(n),reset:n.reset.bind(n),get option(){return n.option},get isHide(){return n.isHide},get isStop(){return n.isStop}}}}n.default=d,d.env="production",d.version="5.0.1",d.build="2023-05-03 11:57:31","undefined"!=typeof window&&(window.artplayerPluginDanmuku=d)},{"./danmuku":"4ns48","./setting":"lO8OT","./heatmap":"8AxLD","@parcel/transformer-js/src/esmodule-helpers.js":"9pCYc"}],"4ns48":[function(t,e,n){var i=t("@parcel/transformer-js/src/esmodule-helpers.js");i.defineInteropFlag(n);var r=t("./bilibili"),a=t("./getDanmuTop"),s=i.interopDefault(a);class o{constructor(e,n){const{constructor:i,template:r}=e;if(this.utils=i.utils,this.validator=i.validator,this.$danmuku=r.$danmuku,this.$player=r.$player,this.art=e,this.danmus=[],this.queue=[],this.option={},this.$refs=[],this.isStop=!1,this.isHide=!1,this.timer=null,this.config(n),this.option.useWorker)try{this.worker=new Worker(t("12ceab24749100d0"))}catch(t){}this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.reset=this.reset.bind(this),this.destroy=this.destroy.bind(this),e.on("video:play",this.start),e.on("video:playing",this.start),e.on("video:pause",this.stop),e.on("video:waiting",this.stop),e.on("resize",this.reset),e.on("destroy",this.destroy),this.load()}static get option(){return{danmuku:[],speed:5,margin:["2%","25%"],opacity:1,color:"#FFFFFF",mode:0,fontSize:25,filter:()=>!0,antiOverlap:!0,useWorker:!0,synchronousPlayback:!1,lockTime:5,maxLength:100,minWidth:200,maxWidth:400,mount:void 0,theme:"dark",heatmap:!1,beforeEmit:()=>!0}}static get scheme(){return{danmuku:"array|function|string",speed:"number",margin:"array",opacity:"number",color:"string",mode:"number",fontSize:"number|string",filter:"function",antiOverlap:"boolean",useWorker:"boolean",synchronousPlayback:"boolean",lockTime:"number",maxLength:"number",minWidth:"number",maxWidth:"number",mount:"undefined|htmldivelement",theme:"string",heatmap:"object|boolean",beforeEmit:"function"}}get isRotate(){return this.art.plugins.autoOrientation&&this.art.plugins.autoOrientation.state}get marginTop(){const{clamp:t}=this.utils,e=this.option.margin[0],{clientHeight:n}=this.$player;if("number"==typeof e)return t(e,0,n);if("string"==typeof e&&e.endsWith("%")){return t(n*(parseFloat(e)/100),0,n)}return o.option.margin[0]}get marginBottom(){const{clamp:t}=this.utils,e=this.option.margin[1],{clientHeight:n}=this.$player;if("number"==typeof e)return t(e,0,n);if("string"==typeof e&&e.endsWith("%")){return t(n*(parseFloat(e)/100),0,n)}return o.option.margin[1]}filter(t,e){return this.queue.filter((e=>e.$state===t)).map(e)}getLeft(t){const e=t.getBoundingClientRect();return this.isRotate?e.top:e.left}getRef(){const t=this.$refs.pop();if(t)return t;const e=document.createElement("div");return e.style.cssText='\n user-select: none;\n position: absolute;\n white-space: pre;\n pointer-events: none;\n perspective: 500px;\n display: inline-block;\n will-change: transform;\n font-weight: normal;\n line-height: 1.125;\n visibility: hidden;\n font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif;\n text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px;\n ',e}getReady(){const{currentTime:t}=this.art;return this.queue.filter((e=>"ready"===e.$state||"wait"===e.$state&&t+.1>=e.time&&e.time>=t-.1))}getEmits(){const t=[],{clientWidth:e}=this.$player,n=this.getLeft(this.$player);return this.filter("emit",(i=>{const r=i.$ref.offsetTop,a=this.getLeft(i.$ref)-n,s=i.$ref.clientHeight,o=i.$ref.clientWidth,l=a+o,u=e-l,d=l/i.$restTime,m={};m.top=r,m.left=a,m.height=s,m.width=o,m.right=u,m.speed=d,m.distance=l,m.time=i.$restTime,m.mode=i.mode,t.push(m)})),t}getFontSize(t){const{clamp:e}=this.utils,{clientHeight:n}=this.$player;if("number"==typeof t)return e(t,12,n);if("string"==typeof t&&t.endsWith("%")){return e(n*(parseFloat(t)/100),12,n)}return o.option.fontSize}postMessage(t={}){return new Promise((e=>{if(this.option.useWorker&&this.worker&&this.worker.postMessage)t.id=Date.now(),this.worker.postMessage(t),this.worker.onmessage=n=>{const{data:i}=n;i.id===t.id&&e(i)};else{const n=(0,s.default)(t);e({top:n})}}))}async load(){try{"function"==typeof this.option.danmuku?this.danmus=await this.option.danmuku():"function"==typeof this.option.danmuku.then?this.danmus=await this.option.danmuku:"string"==typeof this.option.danmuku?this.danmus=await(0,r.bilibiliDanmuParseFromUrl)(this.option.danmuku):this.danmus=this.option.danmuku,this.utils.errorHandle(Array.isArray(this.danmus),"Danmuku need return an array as result"),this.art.emit("artplayerPluginDanmuku:loaded",this.danmus),this.queue=[],this.$danmuku.innerText="",this.danmus.forEach((t=>this.emit(t)))}catch(t){throw this.art.emit("artplayerPluginDanmuku:error",t),t}return this}config(t){const{clamp:e}=this.utils;return this.option=Object.assign({},o.option,this.option,t),this.validator(this.option,o.scheme),this.option.speed=e(this.option.speed,1,10),this.option.opacity=e(this.option.opacity,0,1),this.option.lockTime=e(Math.floor(this.option.lockTime),0,60),this.option.maxLength=e(this.option.maxLength,0,500),this.option.minWidth=e(this.option.minWidth,0,500),this.option.maxWidth=e(this.option.maxWidth,0,1/0),t.fontSize&&(this.option.fontSize=this.getFontSize(this.option.fontSize),this.reset()),this.art.emit("artplayerPluginDanmuku:config",this.option),this}makeWait(t){t.$state="wait",t.$ref&&(t.$ref.style.visibility="hidden",t.$ref.style.marginLeft="0px",t.$ref.style.transform="translateX(0px)",t.$ref.style.transition="transform 0s linear 0s",this.$refs.push(t.$ref),t.$ref=null)}continue(){const{clientWidth:t}=this.$player;return this.filter("stop",(e=>{switch(e.$state="emit",e.$lastStartTime=Date.now(),e.mode){case 0:{const n=t+e.$ref.clientWidth;e.$ref.style.transform=`translateX(${-n}px)`,e.$ref.style.transition=`transform ${e.$restTime}s linear 0s`;break}}})),this}suspend(){const{clientWidth:t}=this.$player;return this.filter("emit",(e=>{switch(e.$state="stop",e.mode){case 0:{const n=t-(this.getLeft(e.$ref)-this.getLeft(this.$player));e.$ref.style.transform=`translateX(${-n}px)`,e.$ref.style.transition="transform 0s linear 0s";break}}})),this}reset(){return this.queue.forEach((t=>this.makeWait(t))),this}update(){return this.timer=window.requestAnimationFrame((async()=>{if(this.art.playing&&!this.isHide){this.filter("emit",(t=>{const e=(Date.now()-t.$lastStartTime)/1e3;t.$restTime-=e,t.$lastStartTime=Date.now(),t.$restTime<=0&&this.makeWait(t)}));const t=this.getReady(),{clientWidth:e,clientHeight:n}=this.$player;for(let i=0;i<t.length;i++){const r=t[i];r.$ref=this.getRef(),r.$ref.innerText=r.text,this.$danmuku.appendChild(r.$ref),r.$ref.style.left=`${e}px`,r.$ref.style.opacity=this.option.opacity,r.$ref.style.fontSize=`${this.option.fontSize}px`,r.$ref.style.color=r.color,r.$ref.style.border=r.border?`1px solid ${r.color}`:null,r.$ref.style.backgroundColor=r.border?"rgb(0 0 0 / 50%)":null,r.$ref.style.marginLeft="0px",r.$lastStartTime=Date.now(),r.$restTime=this.option.synchronousPlayback&&this.art.playbackRate?this.option.speed/Number(this.art.playbackRate):this.option.speed;const a={mode:r.mode,height:r.$ref.clientHeight,speed:(e+r.$ref.clientWidth)/r.$restTime},{top:s}=await this.postMessage({target:a,emits:this.getEmits(),antiOverlap:this.option.antiOverlap,clientWidth:e,clientHeight:n,marginBottom:this.marginBottom,marginTop:this.marginTop});if(r.$ref)if(this.isStop||void 0===s)r.$state="ready",this.$refs.push(r.$ref),r.$ref=null;else switch(r.$state="emit",r.$ref.style.visibility="visible",r.mode){case 0:{r.$ref.style.top=`${s}px`;const t=e+r.$ref.clientWidth;r.$ref.style.transform=`translateX(${-t}px)`,r.$ref.style.transition=`transform ${r.$restTime}s linear 0s`;break}case 1:r.$ref.style.left="50%",r.$ref.style.top=`${s}px`,r.$ref.style.marginLeft=`-${r.$ref.clientWidth/2}px`}}}this.isStop||this.update()})),this}stop(){return this.isStop=!0,this.suspend(),window.cancelAnimationFrame(this.timer),this.art.emit("artplayerPluginDanmuku:stop"),this}start(){return this.isStop=!1,this.continue(),this.update(),this.art.emit("artplayerPluginDanmuku:start"),this}show(){return this.isHide=!1,this.start(),this.$danmuku.style.display="block",this.art.emit("artplayerPluginDanmuku:show"),this}hide(){return this.isHide=!0,this.stop(),this.queue.forEach((t=>this.makeWait(t))),this.$danmuku.style.display="none",this.art.emit("artplayerPluginDanmuku:hide"),this}emit(t){return this.validator(t,{text:"string",mode:"number|undefined",color:"string|undefined",time:"number|undefined",border:"boolean|undefined"}),t.text.trim()&&this.option.filter(t)?(t.time?t.time=this.utils.clamp(t.time,0,1/0):t.time=this.art.currentTime+.5,void 0===t.mode&&(t.mode=this.option.mode),void 0===t.color&&(t.color=this.option.color),this.queue.push({...t,$state:"wait",$ref:null,$restTime:0,$lastStartTime:0}),this):this}destroy(){this.stop(),this.worker&&this.worker.terminate&&this.worker.terminate(),this.art.off("video:play",this.start),this.art.off("video:playing",this.start),this.art.off("video:pause",this.stop),this.art.off("video:waiting",this.stop),this.art.off("resize",this.reset),this.art.off("destroy",this.destroy),this.art.emit("artplayerPluginDanmuku:destroy")}}n.default=o},{"./bilibili":"f83sx","./getDanmuTop":"jPSuD","12ceab24749100d0":"fXq73","@parcel/transformer-js/src/esmodule-helpers.js":"9pCYc"}],f83sx:[function(t,e,n){var i=t("@parcel/transformer-js/src/esmodule-helpers.js");function r(t){switch(t){case 1:case 2:case 3:default:return 0;case 4:case 5:return 1}}function a(t){if("string"!=typeof t)return[];const e=t.matchAll(/<d (?:.*? )??p="(?<p>.+?)"(?: .*?)?>(?<text>.+?)<\/d>/gs);return Array.from(e).map((t=>{const e=t.groups.p.split(",");if(e.length>=8){return{text:t.groups.text.trim().replaceAll(""",'"').replaceAll("'","'").replaceAll("<","<").replaceAll(">",">").replaceAll("&","&"),time:Number(e[0]),mode:r(Number(e[1])),fontSize:Number(e[2]),color:`#${Number(e[3]).toString(16)}`,timestamp:Number(e[4]),pool:Number(e[5]),userID:e[6],rowID:Number(e[7])}}return null})).filter(Boolean)}function s(t){return fetch(t).then((t=>t.text())).then((t=>a(t)))}i.defineInteropFlag(n),i.export(n,"getMode",(()=>r)),i.export(n,"bilibiliDanmuParseFromXml",(()=>a)),i.export(n,"bilibiliDanmuParseFromUrl",(()=>s))},{"@parcel/transformer-js/src/esmodule-helpers.js":"9pCYc"}],"9pCYc":[function(t,e,n){n.interopDefault=function(t){return t&&t.__esModule?t:{default:t}},n.defineInteropFlag=function(t){Object.defineProperty(t,"__esModule",{value:!0})},n.exportAll=function(t,e){return Object.keys(t).forEach((function(n){"default"===n||"__esModule"===n||e.hasOwnProperty(n)||Object.defineProperty(e,n,{enumerable:!0,get:function(){return t[n]}})})),e},n.export=function(t,e,n){Object.defineProperty(t,e,{enumerable:!0,get:n})}},{}],jPSuD:[function(t,e,n){t("@parcel/transformer-js/src/esmodule-helpers.js").defineInteropFlag(n),n.default=function({target:t,emits:e,clientWidth:n,clientHeight:i,marginBottom:r,marginTop:a,antiOverlap:s}){const o=e.filter((e=>e.mode===t.mode&&e.top<=i-r)).sort(((t,e)=>t.top-e.top));if(0===o.length)return a;o.unshift({top:0,left:0,right:0,height:a,width:n,speed:0,distance:n}),o.push({top:i-r,left:0,right:0,height:r,width:n,speed:0,distance:n});for(let e=1;e<o.length;e+=1){const n=o[e],i=o[e-1],r=i.top+i.height;if(n.top-r>=t.height)return r}const l=[];for(let t=1;t<o.length-1;t+=1){const e=o[t];if(l.length){const t=l[l.length-1];t[0].top===e.top?t.push(e):l.push([e])}else l.push([e])}if(!s){switch(t.mode){case 0:l.sort(((t,e)=>{const n=Math.min(...e.map((t=>t.right))),i=Math.min(...t.map((t=>t.right)));return n*e.length-i*t.length}));break;case 1:l.sort(((t,e)=>{const n=Math.max(...e.map((t=>t.width)));return Math.max(...t.map((t=>t.width)))*t.length-n*e.length}))}return l[0][0].top}switch(t.mode){case 0:{const e=l.find((e=>e.every((e=>{if(n<e.distance)return!1;if(t.speed<e.speed)return!0;return e.right/(t.speed-e.speed)>e.time}))));return e&&e[0]?e[0].top:void 0}case 1:return}}},{"@parcel/transformer-js/src/esmodule-helpers.js":"9pCYc"}],fXq73:[function(t,e,n){e.exports="data:application/javascript,function%20getDanmuTop%28%7Btarget%3At%2Cemits%3Ae%2CclientWidth%3An%2CclientHeight%3Ai%2CmarginBottom%3As%2CmarginTop%3Ah%2CantiOverlap%3Ao%7D%29%7Bconst%20r%3De.filter%28%28e%3D%3Ee.mode%3D%3D%3Dt.mode%26%26e.top%3C%3Di-s%29%29.sort%28%28%28t%2Ce%29%3D%3Et.top-e.top%29%29%3Bif%280%3D%3D%3Dr.length%29return%20h%3Br.unshift%28%7Btop%3A0%2Cleft%3A0%2Cright%3A0%2Cheight%3Ah%2Cwidth%3An%2Cspeed%3A0%2Cdistance%3An%7D%29%2Cr.push%28%7Btop%3Ai-s%2Cleft%3A0%2Cright%3A0%2Cheight%3As%2Cwidth%3An%2Cspeed%3A0%2Cdistance%3An%7D%29%3Bfor%28let%20e%3D1%3Be%3Cr.length%3Be%2B%3D1%29%7Bconst%20n%3Dr%5Be%5D%2Ci%3Dr%5Be-1%5D%2Cs%3Di.top%2Bi.height%3Bif%28n.top-s%3E%3Dt.height%29return%20s%7Dconst%20p%3D%5B%5D%3Bfor%28let%20t%3D1%3Bt%3Cr.length-1%3Bt%2B%3D1%29%7Bconst%20e%3Dr%5Bt%5D%3Bif%28p.length%29%7Bconst%20t%3Dp%5Bp.length-1%5D%3Bt%5B0%5D.top%3D%3D%3De.top%3Ft.push%28e%29%3Ap.push%28%5Be%5D%29%7Delse%20p.push%28%5Be%5D%29%7Dif%28%21o%29%7Bswitch%28t.mode%29%7Bcase%200%3Ap.sort%28%28%28t%2Ce%29%3D%3E%7Bconst%20n%3DMath.min%28...e.map%28%28t%3D%3Et.right%29%29%29%2Ci%3DMath.min%28...t.map%28%28t%3D%3Et.right%29%29%29%3Breturn%20n%2ae.length-i%2at.length%7D%29%29%3Bbreak%3Bcase%201%3Ap.sort%28%28%28t%2Ce%29%3D%3E%7Bconst%20n%3DMath.max%28...e.map%28%28t%3D%3Et.width%29%29%29%3Breturn%20Math.max%28...t.map%28%28t%3D%3Et.width%29%29%29%2at.length-n%2ae.length%7D%29%29%7Dreturn%20p%5B0%5D%5B0%5D.top%7Dswitch%28t.mode%29%7Bcase%200%3A%7Bconst%20e%3Dp.find%28%28e%3D%3Ee.every%28%28e%3D%3E%7Bif%28n%3Ce.distance%29return%211%3Bif%28t.speed%3Ce.speed%29return%210%3Breturn%20e.right%2F%28t.speed-e.speed%29%3Ee.time%7D%29%29%29%29%3Breturn%20e%26%26e%5B0%5D%3Fe%5B0%5D.top%3Avoid%200%7Dcase%201%3Areturn%7D%7Donmessage%3Dt%3D%3E%7Bconst%7Bdata%3Ae%7D%3Dt%2Cn%3DgetDanmuTop%28e%29%3Bself.postMessage%28%7Btop%3An%2Cid%3Ae.id%7D%29%7D%3B"},{}],lO8OT:[function(t,e,n){var i=t("@parcel/transformer-js/src/esmodule-helpers.js");i.defineInteropFlag(n);var r=t("bundle-text:./style.less"),a=i.interopDefault(r),s=t("bundle-text:./img/danmu-on.svg"),o=i.interopDefault(s),l=t("bundle-text:./img/danmu-off.svg"),u=i.interopDefault(l),d=t("bundle-text:./img/danmu-config.svg"),m=i.interopDefault(d),p=t("bundle-text:./img/danmu-style.svg"),h=i.interopDefault(p);if(n.default=function(t,e){const{option:n}=e,{template:{$controlsCenter:i,$player:r},constructor:{SETTING_ITEM_WIDTH:a,utils:{removeClass:s,addClass:l,append:d,setStyle:p,tooltip:c,query:f,inverseClass:g,getIcon:y}}}=t;p(i,"display","flex");const k=y("danmu-on",o.default),x=y("danmu-off",u.default),b=y("danmu-config",m.default),v=y("danmu-style",h.default);!function(){const a=["#FE0302","#FF7204","#FFAA02","#FFD302","#FFFF00","#A0EE00","#00CD00","#019899","#4266BE","#89D5FF","#CC0273","#222222","#9B9B9B","#FFFFFF"].map((t=>`<div class="art-danmuku-style-panel-color${n.color===t?" art-current":""}" data-color="${t}" style="background-color:${t}"></div>`)),o=d(i,`<div class="art-danmuku-emitter" style="max-width: ${n.maxWidth?`${n.maxWidth}px`:"100%"}"><div class="art-danmuku-left"><div class="art-danmuku-style"><div class="art-danmuku-style-panel"><div class="art-danmuku-style-panel-inner"><div class="art-danmuku-style-panel-title">模式</div><div class="art-danmuku-style-panel-modes"><div class="art-danmuku-style-panel-mode art-current" data-mode="0">滚动</div><div class="art-danmuku-style-panel-mode" data-mode="1">静止</div></div><div class="art-danmuku-style-panel-title">颜色</div><div class="art-danmuku-style-panel-colors">${a.join("")}</div></div></div></div><input class="art-danmuku-input" maxlength="${n.maxLength}" placeholder="发个弹幕见证当下" /></div><div class="art-danmuku-send">发送</div></div>`),u=f(".art-danmuku-style",o),m=f(".art-danmuku-input",o),h=f(".art-danmuku-send",o),c=f(".art-danmuku-style-panel-inner",o),y=f(".art-danmuku-style-panel-modes",o),k=f(".art-danmuku-style-panel-colors",o),x=n.mount||d(r,'<div class="art-layer-danmuku-emitter"></div>');t.option.backdrop&&l(c,"art-backdrop-filter"),n.theme&&l(o,`art-danmuku-theme-${n.theme}`);let b=null,w=n.mode,$=n.color;function D(t){t<=0?(b=null,h.innerText="发送",s(h,"art-disabled")):(h.innerText=t,b=setTimeout((()=>D(t-1)),1e3))}function B(){const i={mode:w,color:$,border:!0,text:m.value.trim()};null===b&&n.beforeEmit(i)&&(m.value="",e.emit(i),l(h,"art-disabled"),D(n.lockTime),t.emit("artplayerPluginDanmuku:emit",i))}function M(){i.clientWidth<n.minWidth?(d(x,o),p(x,"display","flex"),l(o,"art-danmuku-mount"),n.mount||p(r,"marginBottom","40px")):(d(i,o),p(x,"display","none"),s(o,"art-danmuku-mount"),n.mount||p(r,"marginBottom",null))}d(u,v),t.proxy(h,"click",B),t.proxy(m,"keypress",(t=>{"Enter"===t.key&&(t.preventDefault(),B())})),t.proxy(y,"click",(t=>{const{dataset:e}=t.target;e.mode&&(w=Number(e.mode),g(t.target,"art-current"))})),t.proxy(k,"click",(t=>{const{dataset:e}=t.target;e.color&&($=e.color,g(t.target,"art-current"))})),M(),t.on("resize",(()=>{t.isInput||M()})),t.on("destroy",(()=>{n.mount&&o.parentElement===n.mount&&n.mount.removeChild(o)}))}(),t.controls.add({position:"right",name:"danmuku",click:function(){e.isHide?(e.show(),t.notice.show="弹幕显示",p(k,"display",null),p(x,"display","none")):(e.hide(),t.notice.show="弹幕隐藏",p(k,"display","none"),p(x,"display",null))},mounted(e){d(e,k),d(e,x),c(e,"弹幕开关"),p(x,"display","none"),t.on("artplayerPluginDanmuku:hide",(()=>{p(k,"display","none"),p(x,"display",null)})),t.on("artplayerPluginDanmuku:show",(()=>{p(k,"display",null),p(x,"display","none")}))}}),t.setting.add({width:260,name:"danmuku",html:"弹幕设置",tooltip:"更多",icon:b,selector:[{width:a,html:"播放速度",icon:"",tooltip:"适中",selector:[{html:"极慢",time:10},{html:"较慢",time:7.5},{default:!0,html:"适中",time:5},{html:"较快",time:2.5},{html:"极快",time:1}],onSelect:function(t){return e.config({speed:t.time}),t.html}},{width:a,html:"字体大小",icon:"",tooltip:"适中",selector:[{html:"极小",fontSize:"4%"},{html:"较小",fontSize:"5%"},{default:!0,html:"适中",fontSize:"6%"},{html:"较大",fontSize:"7%"},{html:"极大",fontSize:"8%"}],onSelect:function(t){return e.config({fontSize:t.fontSize}),t.html}},{width:a,html:"不透明度",icon:"",tooltip:"100%",selector:[{default:!0,opacity:1,html:"100%"},{opacity:.75,html:"75%"},{opacity:.5,html:"50%"},{opacity:.25,html:"25%"},{opacity:0,html:"0%"}],onSelect:function(t){return e.config({opacity:t.opacity}),t.html}},{width:a,html:"显示范围",icon:"",tooltip:"3/4",selector:[{html:"1/4",margin:[10,"75%"]},{html:"半屏",margin:[10,"50%"]},{default:!0,html:"3/4",margin:[10,"25%"]},{html:"满屏",margin:[10,10]}],onSelect:function(t){return e.config({margin:t.margin}),t.html}},{html:"弹幕防重叠",icon:"",tooltip:n.antiOverlap?"开启":"关闭",switch:n.antiOverlap,onSwitch:t=>(e.config({antiOverlap:!t.switch}),t.tooltip=t.switch?"关闭":"开启",!t.switch)},{html:"同步视频速度",icon:"",tooltip:n.synchronousPlayback?"开启":"关闭",switch:n.synchronousPlayback,onSwitch:t=>(e.config({synchronousPlayback:!t.switch}),t.tooltip=t.switch?"关闭":"开启",!t.switch)}]})},"undefined"!=typeof document&&!document.getElementById("artplayer-plugin-danmuku")){const t=document.createElement("style");t.id="artplayer-plugin-danmuku",t.textContent=a.default,document.head.appendChild(t)}},{"bundle-text:./style.less":"hViDo","bundle-text:./img/danmu-on.svg":"4KfW9","bundle-text:./img/danmu-off.svg":"9UR3U","bundle-text:./img/danmu-config.svg":"4MPCW","bundle-text:./img/danmu-style.svg":"7lV5Q","@parcel/transformer-js/src/esmodule-helpers.js":"9pCYc"}],hViDo:[function(t,e,n){e.exports='.art-danmuku-emitter{height:32px;width:100%;max-width:100%;background-color:#ffffff4d;border-radius:5px;font-size:12px;line-height:1;display:flex;position:relative}.art-danmuku-emitter .art-backdrop-filter{-webkit-backdrop-filter:saturate(180%)blur(20px);backdrop-filter:saturate(180%)blur(20px);background-color:#000000b3!important}.art-danmuku-emitter .art-danmuku-left{border-radius:3px 0 0 3px;flex:1;display:flex}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style{width:32px;justify-content:center;align-items:center;display:flex;position:relative}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-danmuku-style-panel{z-index:999;width:200px;padding-bottom:10px;display:none;position:absolute;bottom:30px;left:-85px}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-danmuku-style-panel .art-danmuku-style-panel-inner{background-color:#000000e6;border-radius:3px;flex-direction:column;padding:10px 10px 0;display:flex}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-danmuku-style-panel .art-danmuku-style-panel-inner .art-danmuku-style-panel-title{margin-bottom:10px;font-size:13px}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-danmuku-style-panel .art-danmuku-style-panel-inner .art-danmuku-style-panel-modes{justify-content:space-between;margin-bottom:15px;display:flex}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-danmuku-style-panel .art-danmuku-style-panel-inner .art-danmuku-style-panel-modes .art-danmuku-style-panel-mode{width:47%;cursor:pointer;color:#fff;border:1px solid #fff;justify-content:center;padding:5px 0;display:flex}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-danmuku-style-panel .art-danmuku-style-panel-inner .art-danmuku-style-panel-modes .art-danmuku-style-panel-mode.art-current{background-color:#00a1d6;border:1px solid #00a1d6}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-danmuku-style-panel .art-danmuku-style-panel-inner .art-danmuku-style-panel-colors{flex-wrap:wrap;justify-content:space-between;gap:5px;margin-bottom:10px;display:flex}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-danmuku-style-panel .art-danmuku-style-panel-inner .art-danmuku-style-panel-colors .art-danmuku-style-panel-color{cursor:pointer;width:20px;height:20px;border:1px solid #fff}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-danmuku-style-panel .art-danmuku-style-panel-inner .art-danmuku-style-panel-colors .art-danmuku-style-panel-color.art-current{position:relative;box-shadow:0 0 2px #fff}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-danmuku-style-panel .art-danmuku-style-panel-inner .art-danmuku-style-panel-colors .art-danmuku-style-panel-color.art-current:before{content:"";width:100%;height:100%;border:2px solid #000;position:absolute;inset:0}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style:hover .art-danmuku-style-panel{display:flex}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-icon{opacity:.75;cursor:pointer}.art-danmuku-emitter .art-danmuku-left .art-danmuku-style .art-icon:hover{opacity:1}.art-danmuku-emitter .art-danmuku-left .art-danmuku-input{width:100%;color:#fff;background-color:#0000;border:none;outline:none;flex:1;padding:0 10px 0 0;display:flex}.art-danmuku-emitter .art-danmuku-left .art-danmuku-input::placeholder,.art-danmuku-emitter .art-danmuku-left .art-danmuku-input::-webkit-input-placeholder{color:#ffffff80}.art-danmuku-emitter .art-danmuku-send{width:50px;cursor:pointer;background-color:#00a1d6;border-radius:0 5px 5px 0;justify-content:center;align-items:center;display:flex}.art-danmuku-emitter .art-danmuku-send:hover{background-color:#00b5e5}.art-danmuku-emitter .art-danmuku-send.art-disabled{opacity:.5;pointer-events:none}.art-danmuku-emitter.art-danmuku-mount{max-width:100%!important}.art-danmuku-emitter.art-danmuku-mount .art-danmuku-left .art-danmuku-style .art-danmuku-style-panel{left:0}.art-danmuku-emitter.art-danmuku-mount .art-danmuku-send{width:60px}.art-danmuku-emitter.art-danmuku-mount.art-danmuku-theme-light .art-danmuku-left{background:#f4f4f4;border:1px solid #dadada}.art-danmuku-emitter.art-danmuku-mount.art-danmuku-theme-light .art-danmuku-left .art-danmuku-style .art-icon svg{fill:#666}.art-danmuku-emitter.art-danmuku-mount.art-danmuku-theme-light .art-danmuku-left .art-danmuku-input{color:#000}.art-danmuku-emitter.art-danmuku-mount.art-danmuku-theme-light .art-danmuku-left .art-danmuku-input::placeholder,.art-danmuku-emitter.art-danmuku-mount.art-danmuku-theme-light .art-danmuku-left .art-danmuku-input::-webkit-input-placeholder{color:#00000080}.art-layer-danmuku-emitter{z-index:99;width:100%;position:absolute;bottom:-40px;left:0;right:0}'},{}],"4KfW9":[function(t,e,n){e.exports='<svg viewBox="0 0 1152 1024" width="22" height="22" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M311.467 661.333c0 4.267-4.267 8.534-8.534 12.8 0 4.267 0 4.267-4.266 8.534h-12.8c-4.267 0-8.534-4.267-17.067-8.534-8.533-8.533-17.067-8.533-25.6-8.533-8.533 0-12.8 4.267-17.067 12.8-4.266 12.8-8.533 21.333-4.266 29.867 4.266 8.533 12.8 17.066 25.6 21.333 17.066 8.533 34.133 17.067 46.933 17.067 12.8 0 21.333-4.267 34.133-8.534 8.534-4.266 17.067-17.066 25.6-29.866 8.534-12.8 12.8-34.134 17.067-55.467 4.267-21.333 4.267-51.2 4.267-85.333 0-12.8 0-21.334-4.267-29.867 0-8.533-4.267-12.8-8.533-17.067-4.267-4.266-8.534-8.533-12.8-8.533-4.267 0-12.8-4.267-21.334-4.267h-55.466s-4.267-4.266 0-8.533l4.266-38.4c0-4.267 0-8.533 4.267-8.533h46.933c17.067 0 25.6-4.267 34.134-12.8 8.533-8.534 12.8-21.334 12.8-42.667v-72.533c0-17.067-4.267-34.134-8.534-42.667-12.8-12.8-25.6-17.067-42.666-17.067H243.2c-8.533 0-17.067 0-21.333 4.267-4.267 8.533-4.267 12.8-4.267 25.6 0 8.533 0 17.067 4.267 21.333 4.266 4.267 12.8 8.534 21.333 8.534h64c4.267 0 8.533 0 8.533 4.266v34.134c0 8.533 0 12.8-4.266 12.8 0 0-4.267 4.266-8.534 4.266H268.8c-8.533 0-12.8 0-21.333 4.267-4.267 0-8.534 4.267-8.534 4.267-4.266 4.266-8.533 12.8-8.533 17.066 0 8.534-4.267 17.067-4.267 25.6l-8.533 72.534v29.866c0 8.534 4.267 12.8 8.533 17.067 4.267 4.267 8.534 4.267 17.067 8.533h68.267c4.266 0 8.533 0 8.533 4.267s4.267 8.533 4.267 17.067c0 21.333 0 42.666-4.267 55.466 0 8.534-4.267 21.334-8.533 25.6zM896 486.4c-93.867 0-174.933 51.2-217.6 123.733H571.733V576H640c21.333 0 34.133-4.267 42.667-12.8 8.533-8.533 12.8-21.333 12.8-42.667V358.4c0-21.333-4.267-34.133-12.8-42.667-8.534-8.533-21.334-12.8-42.667-12.8 0-4.266 4.267-4.266 4.267-8.533-4.267 0-4.267-4.267-4.267-4.267 4.267-12.8 8.533-21.333 4.267-25.6 0-8.533-4.267-12.8-12.8-21.333-8.534-4.267-17.067-4.267-21.334-4.267-8.533 4.267-12.8 8.534-21.333 21.334-4.267 8.533-8.533 12.8-12.8 21.333-4.267 8.533-8.533 12.8-12.8 21.333H512c-4.267-8.533-8.533-17.066-8.533-21.333-4.267-8.533-8.534-12.8-12.8-21.333-4.267-12.8-12.8-17.067-21.334-17.067s-17.066 0-25.6 8.533c-8.533 8.534-12.8 12.8-12.8 21.334s0 17.066 8.534 25.6l4.266 4.266L448 307.2c-17.067 0-29.867 4.267-38.4 12.8-8.533 4.267-12.8 21.333-12.8 38.4v157.867c0 21.333 4.267 34.133 12.8 42.666 8.533 8.534 21.333 12.8 42.667 12.8H512v34.134h-98.133c-12.8 0-21.334 0-25.6 4.266-4.267 4.267-8.534 8.534-8.534 21.334v17.066c0 4.267 4.267 8.534 4.267 8.534 4.267 0 4.267 4.266 8.533 4.266H512V716.8c0 12.8 4.267 21.333 8.533 25.6 4.267 4.267 12.8 8.533 21.334 8.533 12.8 0 21.333-4.266 25.6-8.533 4.266-4.267 4.266-12.8 4.266-25.6v-55.467H652.8c-8.533 25.6-12.8 51.2-12.8 76.8 0 140.8 115.2 256 256 256s256-115.2 256-256S1036.8 486.4 896 486.4zm-328.533-128h55.466c4.267 0 4.267 0 4.267 4.267V409.6h-59.733v-51.2zm0 102.4H627.2V512h-55.467v-51.2zM512 516.267h-55.467v-51.2H512v51.2zm0-102.4h-59.733V362.667H512v51.2zm384 499.2c-93.867 0-170.667-76.8-170.667-170.667S802.133 571.733 896 571.733s170.667 76.8 170.667 170.667S989.867 913.067 896 913.067z"/><path fill="#fff" d="M951.467 669.867 878.933 742.4l-29.866-25.6C832 699.733 806.4 704 789.333 721.067c-17.066 17.066-12.8 42.666 4.267 59.733l59.733 51.2c8.534 8.533 17.067 8.533 29.867 8.533s21.333-4.266 29.867-12.8l102.4-102.4c17.066-17.066 17.066-42.666 0-59.733-21.334-12.8-46.934-12.8-64 4.267zm-371.2 209.066H213.333c-72.533 0-128-55.466-128-119.466V230.4c0-64 55.467-119.467 128-119.467h512c72.534 0 128 55.467 128 119.467v140.8c0 25.6 17.067 42.667 42.667 42.667s42.667-17.067 42.667-42.667V230.4c0-115.2-93.867-204.8-213.334-204.8h-512C93.867 25.6 0 119.467 0 230.4v529.067c0 115.2 93.867 204.8 213.333 204.8h366.934c25.6 0 42.666-17.067 42.666-42.667s-21.333-42.667-42.666-42.667z"/></svg>'},{}],"9UR3U":[function(t,e,n){e.exports='<svg viewBox="0 0 1152 1024" width="22" height="22" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M311.296 661.504c0 4.096-4.096 8.704-8.704 12.8 0 4.096 0 4.096-4.096 8.704h-12.8c-4.096 0-8.704-4.096-16.896-8.704-8.704-8.704-16.896-8.704-25.6-8.704s-12.8 4.096-16.896 12.8c-4.096 12.8-8.704 21.504-4.096 29.696 4.096 8.704 12.8 16.896 25.6 21.504 16.896 8.704 34.304 16.896 47.104 16.896 12.8 0 21.504-4.096 34.304-8.704 8.704-4.096 16.896-16.896 25.6-29.696s12.8-34.304 16.896-55.296c4.096-21.504 4.096-51.2 4.096-85.504 0-12.8 0-21.504-4.096-29.696 0-8.704-4.096-12.8-8.704-16.896-4.096-4.096-8.704-8.704-12.8-8.704s-12.8-4.096-21.504-4.096h-55.808s-4.096-4.096 0-8.704l4.096-38.4c0-4.096 0-8.704 4.096-8.704h47.104c16.896 0 25.6-4.096 34.304-12.8s12.8-21.504 12.8-42.496v-72.704c0-16.896-4.096-34.304-8.704-42.496-12.8-12.8-25.6-16.896-42.496-16.896H243.2c-8.704 0-16.896 0-21.504 4.096-4.096 8.704-4.096 12.8-4.096 25.6 0 8.704 0 16.896 4.096 21.504 4.096 4.096 12.8 8.704 21.504 8.704h64c4.096 0 8.704 0 8.704 4.096v34.304c0 8.704 0 12.8-4.096 12.8 0 0-4.096 4.096-8.704 4.096H268.8c-8.704 0-12.8 0-21.504 4.096-4.096 0-8.704 4.096-8.704 4.096-4.096 4.096-8.704 12.8-8.704 16.896 0 8.704-4.096 16.896-4.096 25.6l-8.704 72.704v29.696c0 8.704 4.096 12.8 8.704 16.896s8.704 4.096 16.896 8.704h68.096c4.096 0 8.704 0 8.704 4.096s4.096 8.704 4.096 16.896c0 21.504 0 42.496-4.096 55.296.512 9.216-3.584 22.016-8.192 26.624zM896 486.4c-93.696 0-175.104 51.2-217.6 123.904H571.904V576H640c21.504 0 34.304-4.096 42.496-12.8 8.704-8.704 12.8-21.504 12.8-42.496V358.4c0-21.504-4.096-34.304-12.8-42.496-8.704-8.704-21.504-12.8-42.496-12.8 0-4.096 4.096-4.096 4.096-8.704-4.096 0-4.096-4.096-4.096-4.096 4.096-12.8 8.704-21.504 4.096-25.6 0-8.704-4.096-12.8-12.8-21.504-8.704-4.096-16.896-4.096-21.504-4.096-8.704 4.096-12.8 8.704-21.504 21.504-4.096 8.704-8.704 12.8-12.8 21.504s-8.704 12.8-12.8 21.504h-51.2c-4.096-8.704-8.704-16.896-8.704-21.504-4.096-8.704-8.704-12.8-12.8-21.504-4.096-12.8-12.8-16.896-21.504-16.896s-16.896 0-25.6 8.704-12.8 12.8-12.8 21.504 0 16.896 8.704 25.6l4.096 4.096 4.096 4.096c-16.896 0-29.696 4.096-38.4 12.8-8.704 4.096-12.8 21.504-12.8 38.4v157.696c0 21.504 4.096 34.304 12.8 42.496 8.704 8.704 21.504 12.8 42.496 12.8H512v34.304h-98.304c-12.8 0-21.504 0-25.6 4.096s-8.704 8.704-8.704 21.504v16.896c0 4.096 4.096 8.704 4.096 8.704 4.096 0 4.096 4.096 8.704 4.096H512V716.8c0 12.8 4.096 21.504 8.704 25.6 4.096 4.096 12.8 8.704 21.504 8.704 12.8 0 21.504-4.096 25.6-8.704 4.096-4.096 4.096-12.8 4.096-25.6v-55.296H652.8c-8.704 25.6-12.8 51.2-12.8 76.8 0 140.8 115.2 256 256 256s256-115.2 256-256S1036.8 486.4 896 486.4zm-328.704-128h55.296c4.096 0 4.096 0 4.096 4.096V409.6h-59.904v-51.2zm0 102.4H627.2V512h-55.296v-51.2h-4.608zM512 516.096h-55.296v-51.2H512v51.2zm0-102.4h-59.904v-51.2H512v51.2zm384 499.2c-93.696 0-170.496-76.8-170.496-170.496S802.304 571.904 896 571.904s170.496 76.8 170.496 170.496S989.696 912.896 896 912.896z"/><path fill="#fff" d="M580.096 879.104H213.504c-72.704 0-128-55.296-128-119.296V230.4c0-64 55.296-119.296 128-119.296h512c72.704 0 128 55.296 128 119.296v140.8c0 25.6 16.896 42.496 42.496 42.496s42.496-16.896 42.496-42.496V230.4c0-115.2-93.696-204.8-213.504-204.8h-512C93.696 25.6 0 119.296 0 230.4v528.896c0 115.2 93.696 204.8 213.504 204.8h367.104c25.6 0 42.496-16.896 42.496-42.496s-21.504-42.496-43.008-42.496zm171.52 10.752c-15.36-15.36-15.36-40.96 0-56.32l237.568-237.568c15.36-15.36 40.96-15.36 56.32 0s15.36 40.96 0 56.32L807.936 889.856c-15.36 15.36-40.448 15.36-56.32 0z"/></svg>'},{}],"4MPCW":[function(t,e,n){e.exports='<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22"><path d="M16.5 8c1.289 0 2.49.375 3.5 1.022V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h7.022A6.5 6.5 0 0 1 16.5 8zM7 13H5a1 1 0 0 1 0-2h2a1 1 0 0 1 0 2zm2-4H5a1 1 0 0 1 0-2h4a1 1 0 0 1 0 2z"/><path d="m20.587 13.696-.787-.131a3.503 3.503 0 0 0-.593-1.051l.301-.804a.46.46 0 0 0-.21-.56l-1.005-.581a.52.52 0 0 0-.656.113l-.499.607a3.53 3.53 0 0 0-1.276 0l-.499-.607a.52.52 0 0 0-.656-.113l-1.005.581a.46.46 0 0 0-.21.56l.301.804c-.254.31-.456.665-.593 1.051l-.787.131a.48.48 0 0 0-.413.465v1.209a.48.48 0 0 0 .413.465l.811.135c.144.382.353.733.614 1.038l-.292.78a.46.46 0 0 0 .21.56l1.005.581a.52.52 0 0 0 .656-.113l.515-.626a3.549 3.549 0 0 0 1.136 0l.515.626a.52.52 0 0 0 .656.113l1.005-.581a.46.46 0 0 0 .21-.56l-.292-.78c.261-.305.47-.656.614-1.038l.811-.135A.48.48 0 0 0 21 15.37v-1.209a.48.48 0 0 0-.413-.465zM16.5 16.057a1.29 1.29 0 1 1 .002-2.582 1.29 1.29 0 0 1-.002 2.582z"/></svg>'},{}],"7lV5Q":[function(t,e,n){e.exports='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22" width="24" height="24"><path d="M17 16H5c-.55 0-1 .45-1 1s.45 1 1 1h12c.55 0 1-.45 1-1s-.45-1-1-1zM6.96 15c.39 0 .74-.24.89-.6l.65-1.6h5l.66 1.6c.15.36.5.6.89.6.69 0 1.15-.71.88-1.34l-3.88-8.97C11.87 4.27 11.46 4 11 4s-.87.27-1.05.69l-3.88 8.97c-.27.63.2 1.34.89 1.34zM11 5.98 12.87 11H9.13L11 5.98z"/></svg>'},{}],"8AxLD":[function(t,e,n){t("@parcel/transformer-js/src/esmodule-helpers.js").defineInteropFlag(n);const i={map:(t,e,n,i,r)=>(t-e)*(r-i)/(n-e)+i,range(t,e,n){const i=Math.round(t/n)*n;return Array.from({length:Math.floor((e-t)/n)},((t,e)=>e*n+i))}};n.default=function(t,e,n){const{query:r}=t.constructor.utils;t.controls.add({name:"heatmap",position:"top",html:"",style:{position:"absolute",top:"-100px",left:"0px",right:"0px",height:"100px",width:"100%",pointerEvents:"none"},mounted(a){let s=null,o=null;function l(){if(s=null,o=null,a.innerHTML="",!e.danmus.length||!t.duration)return;const l={w:a.offsetWidth,h:a.offsetHeight},u={xMin:0,xMax:l.w,yMin:0,yMax:128,scale:.25,opacity:.2,minHeight:Math.floor(.05*l.h),sampling:Math.floor(l.w/100),smoothing:.2,flattening:.2};"object"==typeof n&&Object.assign(u,n);const d=[],m=t.duration/l.w;for(let t=0;t<=l.w;t+=u.sampling){const n=e.danmus.filter((({time:e})=>e>t*m&&e<=(t+u.sampling)*m)).length;d.push([t,n])}const p=d[d.length-1],h=p[0],c=p[1];h!==l.w&&d.push([l.w,c]);const f=d.map((t=>t[1])),g=(Math.min(...f)+Math.max(...f))/2;for(let t=0;t<d.length;t++){const e=d[t],n=e[1];e[1]=n*(n>g?1+u.scale:1-u.scale)+u.minHeight}const y=(t,e,n,r)=>{const a=((t,e)=>{const n=e[0]-t[0],i=e[1]-t[1];return{length:Math.sqrt(Math.pow(n,2)+Math.pow(i,2)),angle:Math.atan2(i,n)}})(e||t,n||t),s=i.map(Math.cos(a.angle)*u.flattening,0,1,1,0),o=a.angle*s+(r?Math.PI:0),l=a.length*u.smoothing;return[t[0]+Math.cos(o)*l,t[1]+Math.sin(o)*l]},k=d.map((t=>[i.map(t[0],u.xMin,u.xMax,0,l.w),i.map(t[1],u.yMin,u.yMax,l.h,0)])).reduce(((t,e,n,i)=>0===n?`M ${i[i.length-1][0]},${l.h} L ${e[0]},${l.h} L ${e[0]},${e[1]}`:`${t} ${((t,e,n)=>{const i=y(n[e-1],n[e-2],t),r=y(t,n[e-1],n[e+1],!0),a=e===n.length-1?" z":"";return`C ${i[0]},${i[1]} ${r[0]},${r[1]} ${t[0]},${t[1]}${a}`})(e,n,i)}`),"");a.innerHTML=`<svg viewBox="0 0 ${l.w} ${l.h}"><defs><linearGradient id="heatmap-solids" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" style="stop-color:var(--art-theme);stop-opacity:${u.opacity}" /><stop offset="0%" style="stop-color:var(--art-theme);stop-opacity:${u.opacity}" id="heatmap-start" /><stop offset="0%" style="stop-color:var(--art-progress-color);stop-opacity:1" id="heatmap-stop" /><stop offset="100%" style="stop-color:var(--art-progress-color);stop-opacity:1" /></linearGradient></defs><path fill="url(#heatmap-solids)" d="${k}"></path></svg>`,s=r("#heatmap-start",a),o=r("#heatmap-stop",a),s.setAttribute("offset",100*t.played+"%"),o.setAttribute("offset",100*t.played+"%")}t.on("video:timeupdate",(()=>{s&&o&&(s.setAttribute("offset",100*t.played+"%"),o.setAttribute("offset",100*t.played+"%"))})),t.on("setBar",((t,e)=>{s&&o&&"played"===t&&(s.setAttribute("offset",100*e+"%"),o.setAttribute("offset",100*e+"%"))})),t.on("ready",l),t.on("resize",l),t.on("artplayerPluginDanmuku:loaded",l)}})}},{"@parcel/transformer-js/src/esmodule-helpers.js":"9pCYc"}]},["bgm6t"],"bgm6t","parcelRequire4dc0"); | ||
!function(e,t,i,a,n){var o="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},s="function"==typeof o[a]&&o[a],l=s.cache||{},r="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function d(t,i){if(!l[t]){if(!e[t]){var n="function"==typeof o[a]&&o[a];if(!i&&n)return n(t,!0);if(s)return s(t,!0);if(r&&"string"==typeof t)return r(t);var p=Error("Cannot find module '"+t+"'");throw p.code="MODULE_NOT_FOUND",p}h.resolve=function(i){var a=e[t][1][i];return null!=a?a:i},h.cache={};var u=l[t]=new d.Module(t);e[t][0].call(u.exports,h,u,u.exports,this)}return l[t].exports;function h(e){var t=h.resolve(e);return!1===t?{}:d(t)}}d.isParcelRequire=!0,d.Module=function(e){this.id=e,this.bundle=d,this.exports={}},d.modules=e,d.cache=l,d.parent=s,d.register=function(t,i){e[t]=[function(e,t){t.exports=i},{}]},Object.defineProperty(d,"root",{get:function(){return o[a]}}),o[a]=d;for(var p=0;p<t.length;p++)d(t[p]);if(i){var u=d(i);"object"==typeof exports&&"undefined"!=typeof module?module.exports=u:"function"==typeof define&&define.amd&&define(function(){return u})}}({bgm6t:[function(e,t,i){var a=e("@parcel/transformer-js/src/esmodule-helpers.js");a.defineInteropFlag(i),a.export(i,"default",()=>p);var n=e("./danmuku"),o=a.interopDefault(n),s=e("./setting"),l=a.interopDefault(s),r=e("./heatmap"),d=a.interopDefault(r);function p(e){return t=>{let i=new o.default(t,e),a=new l.default(t,i);return i.option.heatmap&&(0,d.default)(t,i,i.option.heatmap),{name:"artplayerPluginDanmuku",emit:i.emit.bind(i),load:i.load.bind(i),config:i.config.bind(i),hide:i.hide.bind(i),show:i.show.bind(i),reset:i.reset.bind(i),mount:a.mount.bind(a),get option(){return i.option},get isHide(){return i.isHide},get isStop(){return i.isStop}}}}p.icons=l.default.icons,"undefined"!=typeof window&&(window.artplayerPluginDanmuku=p)},{"./danmuku":"4ns48","./setting":"lO8OT","./heatmap":"8AxLD","@parcel/transformer-js/src/esmodule-helpers.js":"9pCYc"}],"4ns48":[function(e,t,i){var a=e("@parcel/transformer-js/src/esmodule-helpers.js");a.defineInteropFlag(i);var n=e("./bilibili"),o=e("bundle-text:./worker"),s=a.interopDefault(o);class l{constructor(e,t){let{constructor:i,template:a}=e;this.utils=i.utils,this.validator=i.validator,this.$danmuku=a.$danmuku,this.$player=a.$player,this.art=e,this.danmus=[],this.queue=[],this.option={},this.$refs=[],this.isStop=!1,this.isHide=!1,this.timer=null,this.index=0,this.states={wait:[],ready:[],emit:[],stop:[]},this.config(t),this.worker=new Worker(URL.createObjectURL(new Blob([s.default]))),this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.reset=this.reset.bind(this),this.resize=this.resize.bind(this),this.destroy=this.destroy.bind(this),e.on("video:play",this.start),e.on("video:playing",this.start),e.on("video:pause",this.stop),e.on("video:waiting",this.stop),e.on("destroy",this.destroy),e.on("resize",this.resize),this.load()}static get option(){return{danmuku:[],speed:5,margin:[10,"25%"],opacity:1,color:"#FFFFFF",mode:0,modes:[0,1,2],fontSize:25,antiOverlap:!0,synchronousPlayback:!1,mount:void 0,heatmap:!1,points:[],filter:()=>!0,beforeEmit:()=>!0,beforeVisible:()=>!0,visible:!0,emitter:!0,maxLength:200,lockTime:5,theme:"dark",OPACITY:{},FONT_SIZE:{},MARGIN:{},SPEED:{},COLOR:[]}}static get scheme(){return{danmuku:"array|function|string",speed:"number",margin:"array",opacity:"number",color:"string",mode:"number",modes:"array",fontSize:"number|string",antiOverlap:"boolean",synchronousPlayback:"boolean",mount:"?htmldivelement|string",heatmap:"object|boolean",points:"array",filter:"function",beforeEmit:"function",beforeVisible:"function",visible:"boolean",emitter:"boolean",maxLength:"number",lockTime:"number",theme:"string",OPACITY:"object",FONT_SIZE:"object",MARGIN:"object",SPEED:"object",COLOR:"array"}}static get cssText(){return` user-select: none; position: absolute; white-space: pre; pointer-events: none; perspective: 500px; display: inline-block; will-change: transform; font-weight: normal; line-height: 1.125; visibility: hidden; font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif; text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px; `}get isRotate(){return this.art.plugins?.autoOrientation?.state}get marginTop(){let{clamp:e}=this.utils,t=this.option.margin[0],{clientHeight:i}=this.$player;return"number"==typeof t?e(t,0,i):"string"==typeof t&&t.endsWith("%")?e(i*(parseFloat(t)/100),0,i):l.option.margin[0]}get marginBottom(){let{clamp:e}=this.utils,t=this.option.margin[1],{clientHeight:i}=this.$player;return"number"==typeof t?e(t,0,i):"string"==typeof t&&t.endsWith("%")?e(i*(parseFloat(t)/100),0,i):l.option.margin[1]}get fontSize(){let{clamp:e}=this.utils,{clientHeight:t}=this.$player,i=this.option.fontSize;return"number"==typeof i?e(i,12,t):"string"==typeof i&&i.endsWith("%")?e(t*(parseFloat(i)/100),12,t):l.option.fontSize}get $ref(){let e=this.$refs.pop()||document.createElement("div");return e.style.cssText=l.cssText,e.dataset.mode="",e.className="",e}get readys(){let{currentTime:e}=this.art,t=[];return this.filter("ready",e=>t.push(e)),this.filter("wait",i=>{e+.1>=i.time&&i.time>=e-.1&&t.push(i)}),t}get visibles(){let e=[],{clientWidth:t}=this.$player,i=this.getLeft(this.$player);return this.filter("emit",a=>{let n=a.$ref.offsetTop,o=this.getLeft(a.$ref)-i,s=a.$ref.clientHeight,l=a.$ref.clientWidth,r=o+l,d=r/a.$restTime,p={};p.top=n,p.left=o,p.height=s,p.width=l,p.right=t-r,p.speed=d,p.distance=r,p.time=a.$restTime,p.mode=a.mode,e.push(p)}),e}get speed(){return this.option.synchronousPlayback&&this.art.playbackRate?this.option.speed/Number(this.art.playbackRate):this.option.speed}async load(){let{errorHandle:e}=this.utils;try{"function"==typeof this.option.danmuku?this.danmus=await this.option.danmuku():"function"==typeof this.option.danmuku.then?this.danmus=await this.option.danmuku:"string"==typeof this.option.danmuku?this.danmus=await (0,n.bilibiliDanmuParseFromUrl)(this.option.danmuku):this.danmus=this.option.danmuku,e(Array.isArray(this.danmus),"Danmuku need return an array as result"),this.queue=[],this.$danmuku.innerText="",this.danmus.forEach(e=>this.emit(e)),this.art.emit("artplayerPluginDanmuku:loaded",this.queue)}catch(e){throw this.art.emit("artplayerPluginDanmuku:error",e),e}return this}emit(e){let{clamp:t}=this.utils;if(this.validator(e,{text:"string",mode:"?number",color:"?string",time:"?number",border:"?boolean",style:"?object"}),!e.text.trim()||(e.time?e.time=t(e.time,0,1/0):e.time=this.art.currentTime+.5,void 0===e.mode&&(e.mode=this.option.mode),void 0===e.style&&(e.style={}),void 0===e.color&&(e.color=this.option.color),![0,1,2].includes(e.mode)||!this.option.filter(e)))return this;let i={...e,$state:"wait",$id:this.index++,$ref:null,$restTime:0,$lastStartTime:0};return this.setState(i,"wait"),this.queue.push(i),this}config(e){let{clamp:t}=this.utils,{$controlsCenter:i}=this.art.template;return Object.keys(e).some(t=>JSON.stringify(this.option[t])!==JSON.stringify(e[t]))&&(this.option=Object.assign({},l.option,this.option,e),this.validator(this.option,l.scheme),this.option.mode=t(this.option.mode,0,2),this.option.speed=t(this.option.speed,1,10),this.option.opacity=t(this.option.opacity,0,1),this.option.lockTime=t(this.option.lockTime,1,60),this.option.maxLength=t(this.option.maxLength,1,1e3),this.option.mount=this.option.mount||i,e.fontSize&&this.reset(),this.option.visible?this.show():this.hide(),this.art.emit("artplayerPluginDanmuku:config",this.option)),this}getLeft(e){let t=e.getBoundingClientRect();return this.isRotate?t.top:t.left}postMessage(e={}){return new Promise(t=>{e.id=Date.now(),this.worker.postMessage(e),this.worker.onmessage=i=>{let{data:a}=i;a.id===e.id&&t(a)}})}filter(e,t){let i=this.states[e]||[];for(let e=0;e<i.length;e++)t(i[e]);return i}setState(e,t){this.states[e.$state]=this.states[e.$state].filter(t=>t!==e),e.$state=t,e.$ref&&(e.$ref.dataset.state=t),this.states[t].push(e)}makeWait(e){this.setState(e,"wait"),e.$ref&&(e.$ref.style.cssText=l.cssText,e.$ref.style.visibility="hidden",e.$ref.style.marginLeft="0px",e.$ref.style.transform="translateX(0px)",e.$ref.style.transition="transform 0s linear 0s",this.$refs.push(e.$ref),e.$ref=null)}update(){let{setStyles:e}=this.utils;return this.timer=window.requestAnimationFrame(async()=>{if(this.art.playing&&!this.isHide){this.filter("emit",e=>{let t=(Date.now()-e.$lastStartTime)/1e3;e.$restTime-=t,e.$lastStartTime=Date.now(),e.$restTime<=0&&this.makeWait(e)});let t=this.readys;for(let i=0;i<t.length;i++){let a=t[i];if(await this.option.beforeVisible(a)){let{clientWidth:t,clientHeight:i}=this.$player;a.$ref=this.$ref,a.$ref.innerText=a.text,this.$danmuku.appendChild(a.$ref),a.$ref.style.opacity=this.option.opacity,a.$ref.style.fontSize=`${this.fontSize}px`,a.$ref.style.color=a.color,a.$ref.style.border=a.border?`1px solid ${a.color}`:null,a.$ref.style.backgroundColor=a.border?"rgb(0 0 0 / 50%)":null,e(a.$ref,a.style),a.$lastStartTime=Date.now(),a.$restTime=this.speed;let n=t+a.$ref.clientWidth,{top:o}=await this.postMessage({target:{mode:a.mode,height:a.$ref.clientHeight,speed:n/a.$restTime},visibles:this.visibles,antiOverlap:this.option.antiOverlap,clientWidth:t,clientHeight:i,marginBottom:this.marginBottom,marginTop:this.marginTop});if(a.$ref){if(this.isStop||void 0===o)this.setState(a,"ready"),this.$refs.push(a.$ref),a.$ref=null;else{switch(this.setState(a,"emit"),a.$ref.style.top=`${o}px`,a.$ref.style.visibility="visible",a.$ref.dataset.mode=a.mode,a.mode){case 0:a.$ref.style.left=`${t}px`,a.$ref.style.marginLeft="0px",a.$ref.style.transform=`translateX(${-n}px)`,a.$ref.style.transition=`transform ${a.$restTime}s linear 0s`;break;case 1:case 2:a.$ref.style.left="50%",a.$ref.style.marginLeft=`-${a.$ref.clientWidth/2}px`}this.art.emit("artplayerPluginDanmuku:visible",a)}}}}}this.isStop||this.update()}),this}resize(){let{clientWidth:e}=this.$player;this.filter("stop",t=>{0===t.mode&&(t.$ref.style.left=`${e}px`)}),this.filter("emit",t=>{if(t.$lastStartTime=Date.now(),0===t.mode){let i=e+t.$ref.clientWidth;t.$ref.style.left=`${e}px`,t.$ref.style.transform=`translateX(${-i}px)`,t.$ref.style.transition=`transform ${t.$restTime}s linear 0s`}})}continue(){let{clientWidth:e}=this.$player;return this.filter("stop",t=>{if(this.setState(t,"emit"),t.$lastStartTime=Date.now(),0===t.mode){let i=e+t.$ref.clientWidth;t.$ref.style.transform=`translateX(${-i}px)`,t.$ref.style.transition=`transform ${t.$restTime}s linear 0s`}}),this}suspend(){let{clientWidth:e}=this.$player;return this.filter("emit",t=>{if(this.setState(t,"stop"),0===t.mode){let i=e-(this.getLeft(t.$ref)-this.getLeft(this.$player));t.$ref.style.transform=`translateX(${-i}px)`,t.$ref.style.transition="transform 0s linear 0s"}}),this}stop(){return this.isStop=!0,this.suspend(),window.cancelAnimationFrame(this.timer),this.art.emit("artplayerPluginDanmuku:stop"),this}start(){return this.isStop=!1,this.continue(),this.update(),this.art.emit("artplayerPluginDanmuku:start"),this}reset(){return this.queue.forEach(e=>this.makeWait(e)),this.art.emit("artplayerPluginDanmuku:reset"),this}show(){return this.isHide=!1,this.$danmuku.style.opacity=1,this.option.visible=!0,this.art.emit("artplayerPluginDanmuku:show"),this}hide(){return this.isHide=!0,this.$danmuku.style.opacity=0,this.option.visible=!1,this.art.emit("artplayerPluginDanmuku:hide"),this}destroy(){this.stop(),this.worker.terminate(),this.art.off("video:play",this.start),this.art.off("video:playing",this.start),this.art.off("video:pause",this.stop),this.art.off("video:waiting",this.stop),this.art.off("resize",this.reset),this.art.off("destroy",this.destroy),this.art.emit("artplayerPluginDanmuku:destroy")}}i.default=l},{"./bilibili":"f83sx","bundle-text:./worker":"lfIAi","@parcel/transformer-js/src/esmodule-helpers.js":"9pCYc"}],f83sx:[function(e,t,i){var a=e("@parcel/transformer-js/src/esmodule-helpers.js");function n(e){switch(e){case 1:case 2:case 3:default:return 0;case 4:return 2;case 5:return 1}}function o(e){return"string"!=typeof e?[]:Array.from(e.matchAll(/<d (?:.*? )??p="(?<p>.+?)"(?: .*?)?>(?<text>.+?)<\/d>/gs)).map(e=>{let t=e.groups.p.split(",");return t.length>=8?{text:e.groups.text.trim().replaceAll(""",'"').replaceAll("'","'").replaceAll("<","<").replaceAll(">",">").replaceAll("&","&"),time:Number(t[0]),mode:n(Number(t[1])),fontSize:Number(t[2]),color:`#${Number(t[3]).toString(16)}`,timestamp:Number(t[4]),pool:Number(t[5]),userID:t[6],rowID:Number(t[7])}:null}).filter(Boolean)}async function s(e){let t=await fetch(e);return o(await t.text())}a.defineInteropFlag(i),a.export(i,"getMode",()=>n),a.export(i,"bilibiliDanmuParseFromXml",()=>o),a.export(i,"bilibiliDanmuParseFromUrl",()=>s)},{"@parcel/transformer-js/src/esmodule-helpers.js":"9pCYc"}],"9pCYc":[function(e,t,i){i.interopDefault=function(e){return e&&e.__esModule?e:{default:e}},i.defineInteropFlag=function(e){Object.defineProperty(e,"__esModule",{value:!0})},i.exportAll=function(e,t){return Object.keys(e).forEach(function(i){"default"===i||"__esModule"===i||Object.prototype.hasOwnProperty.call(t,i)||Object.defineProperty(t,i,{enumerable:!0,get:function(){return e[i]}})}),t},i.export=function(e,t,i){Object.defineProperty(e,t,{enumerable:!0,get:i})}},{}],lfIAi:[function(e,t,i){t.exports='!function(e,t,n,o,i){var r="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},f="function"==typeof r[o]&&r[o],l=f.cache||{},d="undefined"!=typeof module&&"function"==typeof module.require&&module.require.bind(module);function u(t,n){if(!l[t]){if(!e[t]){var i="function"==typeof r[o]&&r[o];if(!n&&i)return i(t,!0);if(f)return f(t,!0);if(d&&"string"==typeof t)return d(t);var h=Error("Cannot find module \'"+t+"\'");throw h.code="MODULE_NOT_FOUND",h}p.resolve=function(n){var o=e[t][1][n];return null!=o?o:n},p.cache={};var s=l[t]=new u.Module(t);e[t][0].call(s.exports,p,s,s.exports,this)}return l[t].exports;function p(e){var t=p.resolve(e);return!1===t?{}:u(t)}}u.isParcelRequire=!0,u.Module=function(e){this.id=e,this.bundle=u,this.exports={}},u.modules=e,u.cache=l,u.parent=f,u.register=function(t,n){e[t]=[function(e,t){t.exports=n},{}]},Object.defineProperty(u,"root",{get:function(){return r[o]}}),r[o]=u;for(var h=0;h<t.length;h++)u(t[h]);if(n){var s=u(n);"object"==typeof exports&&"undefined"!=typeof module?module.exports=s:"function"==typeof define&&define.amd&&define(function(){return s})}}({"59OZS":[function(e,t,n){onmessage=e=>{let{data:t}=e;if(!t.id)return;let n=function({target:e,visibles:t,clientWidth:n,clientHeight:o,marginBottom:i,marginTop:r,antiOverlap:f}){let l=o-i,d=t.filter(t=>t.mode===e.mode&&t.top<=l).sort((e,t)=>e.top-t.top);if(0===d.length)return 2===e.mode?l-e.height:r;if(d.unshift({type:"top",top:0,left:0,right:0,height:r,width:n,speed:0,distance:n}),d.push({type:"bottom",top:l,left:0,right:0,height:i,width:n,speed:0,distance:n}),2===e.mode)for(let t=d.length-2;t>=0;t-=1){let n=d[t],o=d[t+1],i=n.top+n.height;if(o.top-i>=e.height)return o.top-e.height}else for(let t=1;t<d.length;t+=1){let n=d[t],o=d[t-1],i=o.top+o.height;if(n.top-i>=e.height)return i}let u=[];for(let e=1;e<d.length-1;e+=1){let t=d[e];if(u.length){let e=u[u.length-1];e[0].top===t.top?e.push(t):u.push([t])}else u.push([t])}if(f)switch(e.mode){case 0:{let t=u.find(t=>t.every(t=>!(n<t.distance)&&(e.speed<t.speed||t.right/(e.speed-t.speed)>t.time)));return t&&t[0]?t[0].top:void 0}case 1:case 2:return}else{switch(e.mode){case 0:u.sort((e,t)=>{let n=Math.min(...t.map(e=>e.right)),o=Math.min(...e.map(e=>e.right));return n*t.length-o*e.length});break;case 1:case 2:u.sort((e,t)=>{let n=Math.max(...t.map(e=>e.width));return Math.max(...e.map(e=>e.width))*e.length-n*t.length})}return u[0][0].top}}(t);self.postMessage({top:n,id:t.id})}},{}]},["59OZS"],"59OZS","parcelRequire4dc0");'},{}],lO8OT:[function(e,t,i){var a=e("@parcel/transformer-js/src/esmodule-helpers.js");a.defineInteropFlag(i);var n=e("bundle-text:./style.less"),o=a.interopDefault(n),s=e("bundle-text:./img/on.svg"),l=a.interopDefault(s),r=e("bundle-text:./img/off.svg"),d=a.interopDefault(r),p=e("bundle-text:./img/config.svg"),u=a.interopDefault(p),h=e("bundle-text:./img/style.svg"),m=a.interopDefault(h),c=e("bundle-text:./img/mode_0_off.svg"),f=a.interopDefault(c),g=e("bundle-text:./img/mode_0_on.svg"),v=a.interopDefault(g),y=e("bundle-text:./img/mode_1_off.svg"),x=a.interopDefault(y),k=e("bundle-text:./img/mode_1_on.svg"),b=a.interopDefault(k),$=e("bundle-text:./img/mode_2_off.svg"),w=a.interopDefault($),M=e("bundle-text:./img/mode_2_on.svg"),E=a.interopDefault(M),D=e("bundle-text:./img/check_on.svg"),S=a.interopDefault(D),z=e("bundle-text:./img/check_off.svg"),A=a.interopDefault(z);if(i.default=class{constructor(e,t){this.art=e,this.danmuku=t,this.utils=e.constructor.utils;let{setStyle:i}=this.utils,{$controlsCenter:a}=e.template;i(a,"display","flex"),this.template={$controlsCenter:a,$mount:a,$danmuku:null,$toggle:null,$configModes:null,$styleModes:null,$colors:null,$opacitySlider:null,$opacityValue:null,$marginSlider:null,$marginValue:null,$fontSizeSlider:null,$fontSizeValue:null,$speedSlider:null,$speedValue:null,$input:null,$send:null},this.slider={opacity:null,margin:null,fontSize:null,speed:null},this.emitting=!1,this.isLock=!1,this.timer=null,this.createTemplate(),this.createSliders(),this.createEvents(),this.mount(this.option.mount),e.on("fullscreen",e=>this.onFullscreen(e)),e.on("fullscreenWeb",e=>this.onFullscreen(e))}static get icons(){return{$on:l.default,$off:d.default,$config:u.default,$style:m.default,$mode_0_off:f.default,$mode_0_on:v.default,$mode_1_off:x.default,$mode_1_on:b.default,$mode_2_off:w.default,$mode_2_on:E.default,$check_on:S.default,$check_off:A.default}}get option(){return this.danmuku.option}get outside(){return this.template.$mount!==this.template.$controlsCenter}get TEMPLATE(){let{option:e}=this;return`<div class="apd-toggle">${l.default}${d.default}</div><div class="apd-config">${u.default}<div class="apd-config-panel"><div class="apd-config-panel-inner"><div class="apd-config-mode">\u{6309}\u{7C7B}\u{578B}\u{5C4F}\u{853D}<div class="apd-modes"><div data-mode="0" class="apd-mode">${f.default}${v.default}<div>\u{6EDA}\u{52A8}</div></div><div data-mode="1" class="apd-mode">${x.default}${b.default}<div>\u{9876}\u{90E8}</div></div><div data-mode="2" class="apd-mode">${w.default}${E.default}<div>\u{5E95}\u{90E8}</div></div></div></div><div class="apd-config-other"><div class="apd-other apd-anti-overlap">${S.default}${A.default} \u{9632}\u{6B62}\u{5F39}\u{5E55}\u{91CD}\u{53E0}</div><div class="apd-other apd-sync-video">${S.default}${A.default} \u{540C}\u{6B65}\u{89C6}\u{9891}\u{901F}\u{5EA6}</div></div><div class="apd-config-slider apd-config-opacity">\u{4E0D}\u{900F}\u{660E}\u{5EA6}<div class="apd-slider"></div><div class="apd-value">\u{672A}\u{77E5}</div></div><div class="apd-config-slider apd-config-margin">\u{663E}\u{793A}\u{533A}\u{57DF}<div class="apd-slider"></div><div class="apd-value">\u{672A}\u{77E5}</div></div><div class="apd-config-slider apd-config-fontSize">\u{5F39}\u{5E55}\u{5B57}\u{53F7}<div class="apd-slider"></div><div class="apd-value">\u{672A}\u{77E5}</div></div><div class="apd-config-slider apd-config-speed">\u{5F39}\u{5E55}\u{901F}\u{5EA6}<div class="apd-slider"></div><div class="apd-value">\u{672A}\u{77E5}</div></div></div></div></div><div class="apd-emitter"><div class="apd-style">${m.default}<div class="apd-style-panel"><div class="apd-style-panel-inner"><div class="apd-style-mode">\u{6A21}\u{5F0F}<div class="apd-modes"><div data-mode="0" class="apd-mode">${v.default}<div>\u{6EDA}\u{52A8}</div></div><div data-mode="1" class="apd-mode">${b.default}<div>\u{9876}\u{90E8}</div></div><div data-mode="2" class="apd-mode">${E.default}<div>\u{5E95}\u{90E8}</div></div></div></div><div class="apd-style-color">\u{989C}\u{8272}<div class="apd-colors">${this.COLOR.map(e=>`<div data-color="${e}" class="apd-color" style="background-color: ${e}"></div>`).join("")}</div></div></div></div></div><input class="apd-input" placeholder="\u{53D1}\u{4E2A}\u{53CB}\u{5584}\u{7684}\u{5F39}\u{5E55}\u{89C1}\u{8BC1}\u{5F53}\u{4E0B}" autocomplete="off" maxLength="${e.maxLength}" /><div class="apd-send">\u{53D1}\u{9001}</div></div>`}get OPACITY(){return{min:0,max:100,steps:[],...this.option.OPACITY}}get FONT_SIZE(){return{min:12,max:120,steps:[],...this.option.FONT_SIZE}}get MARGIN(){return{min:0,max:3,steps:[{name:"1/4",value:[10,"75%"]},{name:"半屏",value:[10,"50%"]},{name:"3/4",value:[10,"25%"]},{name:"满屏",value:[10,10]}],...this.option.MARGIN}}get SPEED(){return{min:0,max:4,steps:[{name:"极慢",value:10},{name:"较慢",value:7.5,hide:!0},{name:"适中",value:5},{name:"较快",value:2.5,hide:!0},{name:"极快",value:1}],...this.option.SPEED}}get COLOR(){return this.option.COLOR.length?this.option.COLOR:["#FE0302","#FF7204","#FFAA02","#FFD302","#FFFF00","#A0EE00","#00CD00","#019899","#4266BE","#89D5FF","#CC0273","#222222","#9B9B9B","#FFFFFF"]}query(e){let{query:t}=this.utils,{$danmuku:i}=this.template;return t(e,i)}setData(e,t){let{$player:i}=this.art.template,{$mount:a}=this.template;i.dataset[e]=t,this.outside&&(a.dataset[e]=t)}createTemplate(){let{createElement:e,tooltip:t}=this.utils,i=e("div");i.className="artplayer-plugin-danmuku",i.innerHTML=this.TEMPLATE,this.template.$danmuku=i,this.template.$toggle=this.query(".apd-toggle"),this.template.$configModes=this.query(".apd-config-mode .apd-modes"),this.template.$styleModes=this.query(".apd-style-mode .apd-modes"),this.template.$colors=this.query(".apd-colors"),this.template.$antiOverlap=this.query(".apd-anti-overlap"),this.template.$syncVideo=this.query(".apd-sync-video"),this.template.$opacitySlider=this.query(".apd-config-opacity .apd-slider"),this.template.$opacityValue=this.query(".apd-config-opacity .apd-value"),this.template.$marginSlider=this.query(".apd-config-margin .apd-slider"),this.template.$marginValue=this.query(".apd-config-margin .apd-value"),this.template.$fontSizeSlider=this.query(".apd-config-fontSize .apd-slider"),this.template.$fontSizeValue=this.query(".apd-config-fontSize .apd-value"),this.template.$speedSlider=this.query(".apd-config-speed .apd-slider"),this.template.$speedValue=this.query(".apd-config-speed .apd-value"),this.template.$input=this.query(".apd-input"),this.template.$send=this.query(".apd-send");let{$toggle:a}=this.template;this.art.on("artplayerPluginDanmuku:show",()=>{t(a,"关闭弹幕")}),this.art.on("artplayerPluginDanmuku:hide",()=>{t(a,"打开弹幕")})}createEvents(){let{$toggle:e,$configModes:t,$styleModes:i,$colors:a,$antiOverlap:n,$syncVideo:o,$send:s,$input:l}=this.template;this.art.proxy(e,"click",()=>{this.danmuku.config({visible:!this.option.visible}),this.reset()}),this.art.proxy(t,"click",e=>{let t=e.target.closest(".apd-mode");if(!t)return;let i=Number(t.dataset.mode);this.option.modes.includes(i)?this.danmuku.config({modes:this.option.modes.filter(e=>e!==i)}):this.danmuku.config({modes:[...this.option.modes,i]}),this.reset()}),this.art.proxy(n,"click",()=>{this.danmuku.config({antiOverlap:!this.option.antiOverlap}),this.reset()}),this.art.proxy(o,"click",()=>{this.danmuku.config({synchronousPlayback:!this.option.synchronousPlayback}),this.reset()}),this.art.proxy(i,"click",e=>{let t=e.target.closest(".apd-mode");if(!t)return;let i=Number(t.dataset.mode);this.danmuku.config({mode:i}),this.reset()}),this.art.proxy(a,"click",e=>{let t=e.target.closest(".apd-color");t&&(this.danmuku.config({color:t.dataset.color}),this.reset())}),this.art.proxy(s,"click",()=>this.emit()),this.art.proxy(l,"keypress",e=>{"Enter"===e.key&&(e.preventDefault(),this.emit())})}createSliders(){this.slider.opacity=this.createSlider({...this.OPACITY,container:this.template.$opacitySlider,findIndex:()=>Math.round(100*this.option.opacity),onChange:e=>{let{$opacityValue:t}=this.template;t.textContent=`${e}%`,this.danmuku.config({opacity:e/100})}}),this.slider.margin=this.createSlider({...this.MARGIN,container:this.template.$marginSlider,findIndex:()=>this.MARGIN.steps.findIndex(e=>e.value[0]===this.option.margin[0]&&e.value[1]===this.option.margin[1]),onChange:e=>{let t=this.MARGIN.steps[e];if(!t)return;let{$marginValue:i}=this.template;i.textContent=t.name,this.danmuku.config({margin:t.value})}}),this.slider.fontSize=this.createSlider({...this.FONT_SIZE,container:this.template.$fontSizeSlider,findIndex:()=>Math.round(this.danmuku.fontSize),onChange:e=>{let{$fontSizeValue:t}=this.template;t.textContent=`${e}px`,this.danmuku.config({fontSize:e})}}),this.slider.speed=this.createSlider({...this.SPEED,container:this.template.$speedSlider,findIndex:()=>this.SPEED.steps.findIndex(e=>e.value===this.option.speed),onChange:e=>{let t=this.SPEED.steps[e];if(!t)return;let{$speedValue:i}=this.template;i.textContent=t.name,this.danmuku.config({speed:t.value})}})}createSlider({min:e,max:t,container:i,findIndex:a,onChange:n,steps:o=[]}){let{query:s,clamp:l}=this.utils;i.innerHTML=`<div class="apd-slider-line"><div class="apd-slider-points">${o.map(()=>'<div class="apd-slider-point"></div>').join("")}</div><div class="apd-slider-progress"></div></div><div class="apd-slider-dot"></div><div class="apd-slider-steps">${o.map(e=>e.hide?"":`<div class="apd-slider-step">${e.name}</div>`).join("")}</div>`;let r=s(".apd-slider-dot",i),d=s(".apd-slider-progress",i),p=!1;function u(i=a()){if(i<e||i>t)return;let s=(i-e)/(t-e);r.style.left=`${100*s}%`,0===o.length&&(d.style.width=r.style.left),n(i)}function h(a){let{left:n,width:o}=i.getBoundingClientRect();u(Math.round(l(a.clientX-n,0,o)/o*(t-e)+e))}return this.art.proxy(i,"click",e=>{h(e)}),this.art.proxy(i,"mousedown",e=>{p=0===e.button}),this.art.on("document:mousemove",e=>{p&&h(e)}),this.art.on("document:mouseup",e=>{p&&(p=!1,h(e))}),{reset:u}}onFullscreen(e){if(this.outside){let{$danmuku:t,$controlsCenter:i,$mount:a}=this.template;e?i.appendChild(t):a.appendChild(t)}}async emit(){let{$input:e}=this.template,t=e.value.trim();if(!t.length||this.isLock||this.emitting)return;let i={text:t,mode:this.option.mode,color:this.option.color,time:this.art.currentTime};try{this.emitting=!0;let t=await this.option.beforeEmit(i);if(this.emitting=!1,!0!==t)return;i.border=!0,delete i.time,this.danmuku.emit(i),e.value="",this.lock()}catch(e){this.emitting=!1}}lock(){let{addClass:e}=this.utils,{$send:t}=this.template;this.isLock=!0;let i=this.option.lockTime;t.innerText=i,e(t,"apd-lock");let a=()=>{this.timer=setTimeout(()=>{0===i?this.unlock():(i-=1,t.innerText=i,a())},1e3)};a()}unlock(){let{removeClass:e}=this.utils,{$send:t}=this.template;clearTimeout(this.timer),this.isLock=!1,t.innerText="发送",e(t,"apd-lock")}reset(){let{inverseClass:e,tooltip:t}=this.utils,{$toggle:i,$colors:a}=this.template;this.slider.opacity.reset(),this.slider.margin.reset(),this.slider.fontSize.reset(),this.slider.speed.reset(),this.setData("danmukuVisible",this.option.visible),this.setData("danmukuMode",this.option.mode),this.setData("danmukuColor",this.option.color),this.setData("danmukuMode0",this.option.modes.includes(0)),this.setData("danmukuMode1",this.option.modes.includes(1)),this.setData("danmukuMode2",this.option.modes.includes(2)),this.setData("danmukuAntiOverlap",this.option.antiOverlap),this.setData("danmukuSyncVideo",this.option.synchronousPlayback),this.setData("danmukuTheme",this.option.theme),this.setData("danmukuEmitter",this.option.emitter);let n=Array.from(a.children).find(e=>e.dataset.color===this.option.color.toUpperCase());n&&e(n,"apd-active"),t(i,this.option.visible?"关闭弹幕":"打开弹幕")}mount(e){let t="string"==typeof e?document.querySelector(e):e;t.appendChild(this.template.$danmuku),this.template.$mount=t,this.reset()}},"undefined"!=typeof document){let e="artplayer-plugin-danmuku",t=document.getElementById(e);if(t)t.textContent=o.default;else{let t=document.createElement("style");t.id=e,t.textContent=o.default,document.head.appendChild(t)}}},{"bundle-text:./style.less":"hViDo","bundle-text:./img/on.svg":"9pjcf","bundle-text:./img/off.svg":"b2dkP","bundle-text:./img/config.svg":"l8tyy","bundle-text:./img/style.svg":"5iZC3","bundle-text:./img/mode_0_off.svg":"i0Vut","bundle-text:./img/mode_0_on.svg":"hOSvZ","bundle-text:./img/mode_1_off.svg":"bOXC3","bundle-text:./img/mode_1_on.svg":"lKuh0","bundle-text:./img/mode_2_off.svg":"eB8W6","bundle-text:./img/mode_2_on.svg":"bpe2E","bundle-text:./img/check_on.svg":"kL9zy","bundle-text:./img/check_off.svg":"22xpM","@parcel/transformer-js/src/esmodule-helpers.js":"9pCYc"}],hViDo:[function(e,t,i){t.exports='.artplayer-plugin-danmuku{z-index:99;color:#fff;flex-shrink:0;justify-content:center;align-items:center;gap:10px;width:100%;height:32px;font-size:12px;font-weight:300;display:flex;position:relative}.artplayer-plugin-danmuku .apd-icon{cursor:pointer;opacity:.75;fill:#fff;transition:all .2s}.artplayer-plugin-danmuku .apd-icon:hover{opacity:1}.artplayer-plugin-danmuku .apd-config{display:flex;position:relative}.artplayer-plugin-danmuku .apd-config .apd-config-panel{width:320px;padding:10px;display:none;position:absolute;bottom:24px;left:-148px}.artplayer-plugin-danmuku .apd-config .apd-config-panel .apd-config-panel-inner{background-color:#000000d9;border-radius:3px;width:100%;padding:10px}.artplayer-plugin-danmuku .apd-config:hover .apd-config-panel{display:flex}.artplayer-plugin-danmuku .apd-config-mode,.artplayer-plugin-danmuku .apd-config-slider,.artplayer-plugin-danmuku .apd-config-other,.artplayer-plugin-danmuku .apd-style-mode{margin-bottom:15px}.artplayer-plugin-danmuku .apd-modes{align-items:center;gap:20px;margin-top:5px;display:flex}.artplayer-plugin-danmuku .apd-modes .apd-mode{cursor:pointer;text-align:center}.artplayer-plugin-danmuku .apd-modes .apd-mode:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-config-slider{align-items:center;gap:12px;display:flex}.artplayer-plugin-danmuku .apd-config-slider .apd-value{text-align:right;width:32px}.artplayer-plugin-danmuku .apd-slider{cursor:pointer;flex:1;justify-content:center;align-items:center;height:20px;display:flex;position:relative}.artplayer-plugin-danmuku .apd-slider .apd-slider-line{background-color:#ffffff40;border-radius:3px;width:100%;height:2px;position:relative;overflow:hidden}.artplayer-plugin-danmuku .apd-slider .apd-slider-points{justify-content:space-between;align-items:center;display:flex;position:absolute;inset:0}.artplayer-plugin-danmuku .apd-slider .apd-slider-points .apd-slider-point{background-color:#ffffff80;border-radius:50%;width:2px;height:2px}.artplayer-plugin-danmuku .apd-slider .apd-slider-progress{background-color:#00a1d6;width:0%;height:100%}.artplayer-plugin-danmuku .apd-slider .apd-slider-dot{background-color:#00a1d6;border-radius:50%;width:12px;height:12px;position:absolute;left:0%;transform:translate(-6px)}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps{color:#777;justify-content:space-between;align-items:center;width:calc(100% + 32px);display:flex;position:absolute;bottom:-12px}.artplayer-plugin-danmuku .apd-slider .apd-slider-steps .apd-slider-step{text-align:center;flex-shrink:0;width:36px;scale:.95}.artplayer-plugin-danmuku .apd-config-other{align-items:center;gap:20px;display:flex}.artplayer-plugin-danmuku .apd-config-other .apd-check-off,.artplayer-plugin-danmuku .apd-config-other .apd-check-on{width:16px;height:16px}.artplayer-plugin-danmuku .apd-config-other .apd-other{cursor:pointer;align-items:center;gap:2px;display:flex}.artplayer-plugin-danmuku .apd-config-other .apd-other:hover{color:#00a1d6}.artplayer-plugin-danmuku .apd-emitter{background-color:#ffffff40;border-radius:5px;flex:1;align-items:center;height:100%;display:flex}.artplayer-plugin-danmuku .apd-style{justify-content:center;align-items:center;display:flex;position:relative}.artplayer-plugin-danmuku .apd-style .apd-style-panel{width:200px;padding:10px;display:none;position:absolute;bottom:24px;left:-88px}.artplayer-plugin-danmuku .apd-style .apd-style-panel .apd-style-panel-inner{background-color:#000000d9;border-radius:3px;width:100%;padding:10px}.artplayer-plugin-danmuku .apd-style:hover .apd-style-panel{display:flex}.artplayer-plugin-danmuku .apd-colors{flex-wrap:wrap;gap:8px;margin-top:5px;display:flex}.artplayer-plugin-danmuku .apd-colors .apd-color{cursor:pointer;border-radius:2px;width:16px;height:16px}.artplayer-plugin-danmuku .apd-colors .apd-color.apd-active{border:1px solid #000;box-shadow:0 0 0 1px #fff}.artplayer-plugin-danmuku .apd-input{color:#fff;background-color:#0000;border:none;outline:none;flex:1;width:auto;min-width:0;height:100%;line-height:1}.artplayer-plugin-danmuku .apd-input::placeholder{color:#ffffff80}.artplayer-plugin-danmuku .apd-send{cursor:pointer;text-shadow:none;background-color:#00a1d6;border-top-right-radius:5px;border-bottom-right-radius:5px;flex-shrink:0;justify-content:center;align-items:center;width:60px;height:100%;display:flex}.artplayer-plugin-danmuku .apd-send.apd-lock{cursor:not-allowed;color:#666;background-color:#e7e7e7}.art-controls-center .apd-emitter{flex:none;width:260px}.art-fullscreen .artplayer-plugin-danmuku,.art-fullscreen-web .artplayer-plugin-danmuku{gap:16px;height:38px}.art-fullscreen .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen-web .artplayer-plugin-danmuku .apd-config-icon,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-off,.art-fullscreen .artplayer-plugin-danmuku .apd-toggle-on,.art-fullscreen-web .artplayer-plugin-danmuku .apd-toggle-on{width:28px;height:28px}.art-fullscreen .artplayer-plugin-danmuku .apd-emitter,.art-fullscreen-web .artplayer-plugin-danmuku .apd-emitter{flex:none;width:400px}[data-danmuku-emitter=false] .apd-emitter{display:none!important}[data-danmuku-emitter=false] .art-controls-center .artplayer-plugin-danmuku{justify-content:flex-end;gap:18px}[data-danmuku-emitter=false].art-fullscreen .art-controls-center .artplayer-plugin-danmuku,[data-danmuku-emitter=false].art-fullscreen-web .art-controls-center .artplayer-plugin-danmuku{gap:24px}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-icon{fill:#333}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-emitter{background-color:#f1f2f3}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input{color:#000}[data-danmuku-theme=light]>.artplayer-plugin-danmuku .apd-input::placeholder{color:#0000004d}[data-danmuku-visible=false] .apd-toggle-off{display:block}[data-danmuku-visible=false] .apd-toggle-on,[data-danmuku-visible=true] .apd-toggle-off{display:none}[data-danmuku-visible=true] .apd-toggle-on{display:block}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-on{display:none}[data-danmuku-anti-overlap=false] .apd-anti-overlap .apd-check-off,[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-on{display:block}[data-danmuku-anti-overlap=true] .apd-anti-overlap .apd-check-off,[data-danmuku-sync-video=false] .apd-sync-video .apd-check-on{display:none}[data-danmuku-sync-video=false] .apd-sync-video .apd-check-off,[data-danmuku-sync-video=true] .apd-sync-video .apd-check-on{display:block}[data-danmuku-sync-video=true] .apd-sync-video .apd-check-off{display:none}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-off{display:block}[data-danmuku-mode0=false] .apd-config-mode .apd-mode-0-on{display:none}[data-danmuku-mode0=false] .art-danmuku [data-mode="0"]{opacity:0!important}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-off{display:none}[data-danmuku-mode0=true] .apd-config-mode .apd-mode-0-on{display:block}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"]{color:#00a1d6}[data-danmuku-mode="0"] .apd-style-mode [data-mode="0"] path{fill:#00a1d6}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-off{display:block}[data-danmuku-mode1=false] .apd-config-mode .apd-mode-1-on{display:none}[data-danmuku-mode1=false] .art-danmuku [data-mode="1"]{opacity:0!important}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-off{display:none}[data-danmuku-mode1=true] .apd-config-mode .apd-mode-1-on{display:block}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"]{color:#00a1d6}[data-danmuku-mode="1"] .apd-style-mode [data-mode="1"] path{fill:#00a1d6}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-off{display:block}[data-danmuku-mode2=false] .apd-config-mode .apd-mode-2-on{display:none}[data-danmuku-mode2=false] .art-danmuku [data-mode="2"]{opacity:0!important}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-off{display:none}[data-danmuku-mode2=true] .apd-config-mode .apd-mode-2-on{display:block}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"]{color:#00a1d6}[data-danmuku-mode="2"] .apd-style-mode [data-mode="2"] path{fill:#00a1d6}'},{}],"9pjcf":[function(e,t,i){t.exports='<svg class="apd-icon apd-toggle-on" xmlns="http://www.w3.org/2000/svg" data-pointer="none" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="M11.989 4.828c-.47 0-.975.004-1.515.012l-1.71-2.566a1.008 1.008 0 0 0-1.678 1.118l.999 1.5c-.681.018-1.403.04-2.164.068a4.013 4.013 0 0 0-3.83 3.44c-.165 1.15-.245 2.545-.245 4.185 0 1.965.115 3.67.35 5.116a4.012 4.012 0 0 0 3.763 3.363l.906.046c1.205.063 1.808.095 3.607.095a.988.988 0 0 0 0-1.975c-1.758 0-2.339-.03-3.501-.092l-.915-.047a2.037 2.037 0 0 1-1.91-1.708c-.216-1.324-.325-2.924-.325-4.798 0-1.563.076-2.864.225-3.904.14-.977.96-1.713 1.945-1.747 2.444-.087 4.465-.13 6.063-.131 1.598 0 3.62.044 6.064.13.96.034 1.71.81 1.855 1.814.075.524.113 1.962.141 3.065v.002c.01.342.017.65.025.88a.987.987 0 1 0 1.974-.068c-.008-.226-.016-.523-.025-.856v-.027c-.03-1.118-.073-2.663-.16-3.276-.273-1.906-1.783-3.438-3.74-3.507-.9-.032-1.743-.058-2.531-.078l1.05-1.46a1.008 1.008 0 0 0-1.638-1.177l-1.862 2.59c-.38-.004-.744-.007-1.088-.007h-.13Zm.521 4.775h-1.32v4.631h2.222v.847h-2.618v1.078h2.618l.003.678c.36.026.714.163 1.01.407h.11v-1.085h2.694v-1.078h-2.695v-.847H16.8v-4.63h-1.276a8.59 8.59 0 0 0 .748-1.42L15.183 7.8a14.232 14.232 0 0 1-.814 1.804h-1.518l.693-.308a8.862 8.862 0 0 0-.814-1.408l-1.045.352c.297.396.572.847.825 1.364Zm-4.18 3.564.154-1.485h1.98V8.294h-3.2v.98H9.33v1.43H7.472l-.308 3.453h2.277c0 1.166-.044 1.925-.12 2.277-.078.352-.386.528-.936.528-.308 0-.616-.022-.902-.055l.297 1.067.062.005c.285.02.551.04.818.04 1.001-.067 1.562-.419 1.694-1.057.11-.638.176-1.903.176-3.795h-2.2Zm7.458.11v-.858h-1.254v.858h1.254Zm-2.376-.858v.858h-1.199v-.858h1.2Zm-1.199-.946h1.2v-.902h-1.2v.902Zm2.321 0v-.902h1.254v.902h-1.254Z" clip-rule="evenodd"/><path fill="#00AEEC" fill-rule="evenodd" d="M22.846 14.627a1 1 0 0 0-1.412.075l-5.091 5.703-2.216-2.275-.097-.086-.008-.005a1 1 0 0 0-1.322 1.493l2.963 3.041.093.083.007.005a1 1 0 0 0 1.354-.124l5.81-6.505.08-.102.005-.008a1 1 0 0 0-.166-1.295Z" clip-rule="evenodd"/></svg>'},{}],b2dkP:[function(e,t,i){t.exports='<svg class="apd-icon apd-toggle-off" xmlns="http://www.w3.org/2000/svg" data-pointer="none" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="m8.085 4.891-.999-1.499a1.008 1.008 0 0 1 1.679-1.118l1.709 2.566c.54-.008 1.045-.012 1.515-.012h.13c.345 0 .707.003 1.088.007l1.862-2.59a1.008 1.008 0 0 1 1.637 1.177l-1.049 1.46c.788.02 1.631.046 2.53.078 1.958.069 3.468 1.6 3.74 3.507.088.613.13 2.158.16 3.276l.001.027c.01.333.017.63.025.856a.987.987 0 0 1-1.974.069c-.008-.23-.016-.539-.025-.881v-.002c-.028-1.103-.066-2.541-.142-3.065-.143-1.004-.895-1.78-1.854-1.813a179.14 179.14 0 0 0-6.064-.131c-1.598 0-3.619.044-6.063.13a2.037 2.037 0 0 0-1.945 1.748c-.15 1.04-.225 2.341-.225 3.904 0 1.874.11 3.474.325 4.798.154.949.95 1.66 1.91 1.708a97.58 97.58 0 0 0 5.416.139.988.988 0 0 1 0 1.975 99.78 99.78 0 0 1-5.513-.141A4.012 4.012 0 0 1 2.197 17.7c-.236-1.446-.351-3.151-.351-5.116 0-1.64.08-3.035.245-4.184A4.013 4.013 0 0 1 5.92 4.96c.761-.027 1.483-.05 2.164-.069Zm4.436 4.707h-1.32v4.63h2.222v.848h-2.618v1.078h2.431a5.01 5.01 0 0 1 3.575-3.115V9.598h-1.276a8.59 8.59 0 0 0 .748-1.42l-1.089-.384a14.232 14.232 0 0 1-.814 1.804h-1.518l.693-.308a8.862 8.862 0 0 0-.814-1.408l-1.045.352c.297.396.572.847.825 1.364Zm-4.18 3.564.154-1.485h1.98V8.289h-3.2v.979h2.067v1.43H7.483l-.308 3.454h2.277c0 1.166-.044 1.925-.12 2.277-.078.352-.386.528-.936.528-.308 0-.616-.022-.902-.055l.297 1.067.062.004c.285.02.551.04.818.04 1.001-.066 1.562-.418 1.694-1.056.11-.638.176-1.903.176-3.795h-2.2Zm7.458.11v-.858h-1.254v.858H15.8Zm-2.376-.858v.858h-1.199v-.858h1.2Zm-1.199-.946h1.2v-.902h-1.2v.902Zm2.321 0v-.902H15.8v.902h-1.254Zm3.517 10.594a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm-.002-1.502a2.5 2.5 0 0 1-2.217-3.657l3.326 3.398a2.49 2.49 0 0 1-1.109.259Zm2.5-2.5c0 .42-.103.815-.286 1.162l-3.328-3.401a2.5 2.5 0 0 1 3.614 2.239Z" clip-rule="evenodd"/></svg>'},{}],l8tyy:[function(e,t,i){t.exports='<svg class="apd-icon apd-config-icon" xmlns="http://www.w3.org/2000/svg" data-pointer="none" viewBox="0 0 24 24" width="24" height="24"><path fill-rule="evenodd" d="m15.645 4.881 1.06-1.473a.998.998 0 1 0-1.622-1.166L13.22 4.835a110.67 110.67 0 0 0-1.1-.007h-.131c-.47 0-.975.004-1.515.012L8.783 2.3A.998.998 0 0 0 7.12 3.408l.988 1.484c-.688.019-1.418.042-2.188.069a4.013 4.013 0 0 0-3.83 3.44c-.165 1.15-.245 2.545-.245 4.185 0 1.965.115 3.67.35 5.116a4.012 4.012 0 0 0 3.763 3.363 99.78 99.78 0 0 0 5.513.141.988.988 0 0 0 0-1.975 97.58 97.58 0 0 1-5.416-.139 2.037 2.037 0 0 1-1.91-1.708c-.216-1.324-.325-2.924-.325-4.798 0-1.563.076-2.864.225-3.904.14-.977.96-1.713 1.945-1.747 2.444-.087 4.465-.13 6.063-.131 1.598 0 3.62.044 6.064.13.96.034 1.71.81 1.855 1.814.075.524.113 1.962.141 3.065v.002c.005.183.01.07.014-.038.004-.096.008-.189.011-.081a.987.987 0 1 0 1.974-.069c-.004-.105-.007-.009-.011.09a2.175 2.175 0 0 1-.007.135l-.002.01a.574.574 0 0 1-.005-.091v-.027c-.03-1.118-.073-2.663-.16-3.276-.273-1.906-1.783-3.438-3.74-3.507-.905-.032-1.752-.058-2.543-.079Zm-3.113 4.703h-1.307v4.643h2.2v.04l.651-1.234c.113-.215.281-.389.482-.509v-.11h.235c.137-.049.283-.074.433-.074h1.553V9.584h-1.264a8.5 8.5 0 0 0 .741-1.405l-1.078-.381c-.24.631-.501 1.23-.806 1.786h-1.503l.686-.305a8.613 8.613 0 0 0-.806-1.394l-1.034.348c.294.392.566.839.817 1.35Zm-1.7 5.502h2.16l-.564 1.068h-1.595v-1.068Zm-2.498-1.863.152-1.561h1.96V8.289H7.277v.969h2.048v1.435h-1.84l-.306 3.51h2.254c0 1.155-.043 1.906-.12 2.255-.076.348-.38.523-.925.523-.305 0-.61-.022-.893-.055l.294 1.056.061.005c.282.02.546.039.81.039.991-.065 1.547-.414 1.677-1.046.11-.631.175-1.883.175-3.757H8.334Zm5.09-.8v.85h-1.188v-.85h1.187Zm-1.188-.955h1.187v-.893h-1.187v.893Zm2.322.007v-.893h1.241v.893h-1.241Zm.528 2.757a1.26 1.26 0 0 1 1.087-.627l4.003-.009a1.26 1.26 0 0 1 1.094.63l1.721 2.982c.226.39.225.872-.001 1.263l-1.743 3a1.26 1.26 0 0 1-1.086.628l-4.003.009a1.26 1.26 0 0 1-1.094-.63l-1.722-2.982a1.26 1.26 0 0 1 .002-1.263l1.742-3Zm1.967.858a1.26 1.26 0 0 0-1.08.614l-.903 1.513a1.26 1.26 0 0 0-.002 1.289l.885 1.492c.227.384.64.62 1.086.618l2.192-.005a1.26 1.26 0 0 0 1.08-.615l.904-1.518a1.26 1.26 0 0 0 .001-1.288l-.884-1.489a1.26 1.26 0 0 0-1.086-.616l-2.193.005Zm2.517 2.76a1.4 1.4 0 1 1-2.8 0 1.4 1.4 0 0 1 2.8 0Z" clip-rule="evenodd"/></svg>'},{}],"5iZC3":[function(e,t,i){t.exports='<svg class="apd-icon apd-style-icon" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" data-pointer="none" style="enable-background:new 0 0 22 22" viewBox="0 0 22 22" width="36" height="24"><path d="M17 16H5c-.55 0-1 .45-1 1s.45 1 1 1h12c.55 0 1-.45 1-1s-.45-1-1-1zM6.96 15c.39 0 .74-.24.89-.6l.65-1.6h5l.66 1.6c.15.36.5.6.89.6.69 0 1.15-.71.88-1.34l-3.88-8.97C11.87 4.27 11.46 4 11 4s-.87.27-1.05.69l-3.88 8.97c-.27.63.2 1.34.89 1.34zM11 5.98 12.87 11H9.13L11 5.98z"/></svg>'},{}],i0Vut:[function(e,t,i){t.exports='<svg class="apd-icon apd-mode-0-off" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" data-pointer="none" style="enable-background:new 0 0 28 28" viewBox="0 0 28 28" width="28" height="28"><path d="M23 15c1.487 0 2.866.464 4 1.255V7a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v14a4 4 0 0 0 4 4h11.674A7 7 0 0 1 23 15zM11 9h6a1 1 0 0 1 0 2h-6a1 1 0 0 1 0-2zm-3 2H6V9h2v2zm4 4h-2v-2h2v2zm2-1a1 1 0 0 1 1-1h1a1 1 0 0 1 0 2h-1a1 1 0 0 1-1-1z" fill="#00AEEC"/><path d="M26.536 18.464a5 5 0 0 0-7.071 0 5 5 0 0 0 0 7.071 5 5 0 1 0 7.071-7.071zm-5.657 5.657a3 3 0 0 1-.586-3.415l4.001 4.001a3 3 0 0 1-3.415-.586zm4.829-.827-4.001-4.001a3.002 3.002 0 0 1 4.001 4.001z" fill="#00AEEC"/></svg>'},{}],hOSvZ:[function(e,t,i){t.exports='<svg class="apd-icon apd-mode-0-on" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" data-pointer="none" style="enable-background:new 0 0 28 28" viewBox="0 0 28 28" width="28" height="28"><path d="M23 3H5a4 4 0 0 0-4 4v14a4 4 0 0 0 4 4h18a4 4 0 0 0 4-4V7a4 4 0 0 0-4-4zM11 9h6a1 1 0 0 1 0 2h-6a1 1 0 0 1 0-2zm-3 2H6V9h2v2zm4 4h-2v-2h2v2zm9 0h-6a1 1 0 0 1 0-2h6a1 1 0 0 1 0 2z" fill="#FFF"/></svg>'},{}],bOXC3:[function(e,t,i){t.exports='<svg class="apd-icon apd-mode-1-off" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" data-pointer="none" style="enable-background:new 0 0 28 28" viewBox="0 0 28 28" width="28" height="28"><path d="M23 15c1.487 0 2.866.464 4 1.255V7a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v14a4 4 0 0 0 4 4h11.674A7 7 0 0 1 23 15zm-4-8h2v2h-2V7zM9 9H7V7h2v2zm4 0h-2V7h2v2zm2-2h2v2h-2V7z" fill="#00AEEC"/><path d="M26.536 18.464a5 5 0 0 0-7.071 0 5 5 0 0 0 0 7.071 5 5 0 1 0 7.071-7.071zm-5.657 5.657a3 3 0 0 1-.586-3.415l4.001 4.001a3 3 0 0 1-3.415-.586zm4.829-.827-4.001-4.001a3.002 3.002 0 0 1 4.001 4.001z" fill="#00AEEC"/></svg>'},{}],lKuh0:[function(e,t,i){t.exports='<svg class="apd-icon apd-mode-1-on" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" data-pointer="none" style="enable-background:new 0 0 28 28" viewBox="0 0 28 28" width="28" height="28"><path d="M23 3H5a4 4 0 0 0-4 4v14a4 4 0 0 0 4 4h18a4 4 0 0 0 4-4V7a4 4 0 0 0-4-4zM9 9H7V7h2v2zm4 0h-2V7h2v2zm4 0h-2V7h2v2zm4 0h-2V7h2v2z" fill="#FFF"/></svg>'},{}],eB8W6:[function(e,t,i){t.exports='<svg class="apd-icon apd-mode-2-off" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" data-pointer="none" style="enable-background:new 0 0 28 28" viewBox="0 0 28 28" width="28" height="28"><path d="M23 15c1.487 0 2.866.464 4 1.255V7a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v14a4 4 0 0 0 4 4h11.674A7 7 0 0 1 23 15zM9 21H7v-2h2v2zm4 0h-2v-2h2v2z" fill="#00AEEC"/><path d="M26.536 18.464a5 5 0 0 0-7.071 0 5 5 0 0 0 0 7.071 5 5 0 1 0 7.071-7.071zm-5.657 5.657a3 3 0 0 1-.586-3.415l4.001 4.001a3 3 0 0 1-3.415-.586zm4.829-.827-4.001-4.001a3.002 3.002 0 0 1 4.001 4.001z" fill="#00AEEC"/></svg>'},{}],bpe2E:[function(e,t,i){t.exports='<svg class="apd-icon apd-mode-2-on" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" data-pointer="none" style="enable-background:new 0 0 28 28" viewBox="0 0 28 28" width="28" height="28"><path d="M23 3H5a4 4 0 0 0-4 4v14a4 4 0 0 0 4 4h18a4 4 0 0 0 4-4V7a4 4 0 0 0-4-4zM9 21H7v-2h2v2zm4 0h-2v-2h2v2zm4 0h-2v-2h2v2zm4 0h-2v-2h2v2z" fill="#FFF"/></svg>'},{}],kL9zy:[function(e,t,i){t.exports='<svg class="apd-icon apd-check-on" xmlns="http://www.w3.org/2000/svg" data-pointer="none" viewBox="0 0 32 32" width="32" height="32"><path d="m13 18.25-1.8-1.8c-.6-.6-1.65-.6-2.25 0s-.6 1.5 0 2.25l2.85 2.85c.318.318.762.468 1.2.448.438.02.882-.13 1.2-.448l8.85-8.85c.6-.6.6-1.65 0-2.25s-1.65-.6-2.25 0l-7.8 7.8zM8 4h16c2.21 0 4 1.79 4 4v16c0 2.21-1.79 4-4 4H8c-2.21 0-4-1.79-4-4V8c0-2.21 1.79-4 4-4z" fill="#00AEEC"/></svg>'},{}],"22xpM":[function(e,t,i){t.exports='<svg class="apd-icon apd-check-off" xmlns="http://www.w3.org/2000/svg" data-pointer="none" viewBox="0 0 32 32" width="32" height="32"><path d="M8 6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2H8zm0-2h16c2.21 0 4 1.79 4 4v16c0 2.21-1.79 4-4 4H8c-2.21 0-4-1.79-4-4V8c0-2.21 1.79-4 4-4z" fill="#FFF"/></svg>'},{}],"8AxLD":[function(e,t,i){var a=e("@parcel/transformer-js/src/esmodule-helpers.js");a.defineInteropFlag(i),a.export(i,"default",()=>s);let n={map:(e,t,i,a,n)=>(e-t)*(n-a)/(i-t)+a,range(e,t,i){let a=Math.round(e/i)*i;return Array.from({length:Math.floor((t-e)/i)},(e,t)=>t*i+a)}},o=(e,t)=>{let i=t[0]-e[0],a=t[1]-e[1];return{length:Math.sqrt(Math.pow(i,2)+Math.pow(a,2)),angle:Math.atan2(a,i)}};function s(e,t,i){let{query:a}=e.constructor.utils;e.controls.add({name:"heatmap",position:"top",html:"",style:{position:"absolute",top:"-100px",left:"0px",right:"0px",height:"100px",width:"100%",pointerEvents:"none"},mounted(s){let l=null,r=null;function d(d=[]){if(l=null,r=null,s.innerHTML="",!e.duration||e.option.isLive)return;let p={w:s.offsetWidth,h:s.offsetHeight},u={xMin:0,xMax:p.w,yMin:0,yMax:128,scale:.25,opacity:.2,minHeight:Math.floor(.05*p.h),sampling:Math.floor(p.w/100),smoothing:.2,flattening:.2};"object"==typeof i&&Object.assign(u,i);let h=[];if(Array.isArray(d)&&d.length)h=[...d];else{let i=e.duration/p.w;for(let e=0;e<=p.w;e+=u.sampling){let a=t.danmus.filter(({time:t})=>t>e*i&&t<=(e+u.sampling)*i).length;h.push([e,a])}}if(0===h.length)return;let m=h[h.length-1],c=m[0],f=m[1];c!==p.w&&h.push([p.w,f]);let g=h.map(e=>e[1]),v=(Math.min(...g)+Math.max(...g))/2;for(let e=0;e<h.length;e++){let t=h[e],i=t[1];t[1]=i*(i>v?1+u.scale:1-u.scale)+u.minHeight}let y=(e,t,i,a)=>{let s=o(t||e,i||e),l=n.map(Math.cos(s.angle)*u.flattening,0,1,1,0),r=s.angle*l+(a?Math.PI:0),d=s.length*u.smoothing;return[e[0]+Math.cos(r)*d,e[1]+Math.sin(r)*d]},x=(e,t,i)=>{let a=y(i[t-1],i[t-2],e),n=y(e,i[t-1],i[t+1],!0),o=t===i.length-1?" z":"";return`C ${a[0]},${a[1]} ${n[0]},${n[1]} ${e[0]},${e[1]}${o}`},k=h.map(e=>[n.map(e[0],u.xMin,u.xMax,0,p.w),n.map(e[1],u.yMin,u.yMax,p.h,0)]).reduce((e,t,i,a)=>0===i?`M ${a[a.length-1][0]},${p.h} L ${t[0]},${p.h} L ${t[0]},${t[1]}`:`${e} ${x(t,i,a)}`,"");s.innerHTML=`<svg viewBox="0 0 ${p.w} ${p.h}"><defs><linearGradient id="heatmap-solids" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" style="stop-color:var(--art-theme);stop-opacity:${u.opacity}" /><stop offset="0%" style="stop-color:var(--art-theme);stop-opacity:${u.opacity}" id="heatmap-start" /><stop offset="0%" style="stop-color:var(--art-progress-color);stop-opacity:1" id="heatmap-stop" /><stop offset="100%" style="stop-color:var(--art-progress-color);stop-opacity:1" /></linearGradient></defs><path fill="url(#heatmap-solids)" d="${k}"></path></svg>`,l=a("#heatmap-start",s),r=a("#heatmap-stop",s),l.setAttribute("offset",`${100*e.played}%`),r.setAttribute("offset",`${100*e.played}%`)}e.on("video:timeupdate",()=>{l&&r&&(l.setAttribute("offset",`${100*e.played}%`),r.setAttribute("offset",`${100*e.played}%`))}),e.on("setBar",(e,t)=>{l&&r&&"played"===e&&(l.setAttribute("offset",`${100*t}%`),r.setAttribute("offset",`${100*t}%`))}),e.on("ready",()=>d()),e.on("resize",()=>d()),e.on("artplayerPluginDanmuku:loaded",()=>d()),e.on("artplayerPluginDanmuku:points",e=>d(e))}})}},{"@parcel/transformer-js/src/esmodule-helpers.js":"9pCYc"}]},["bgm6t"],"bgm6t","parcelRequire4dc0"); |
{ | ||
"license": "MIT", | ||
"version": "5.0.1", | ||
"version": "5.1.0", | ||
"name": "artplayer-plugin-danmuku", | ||
@@ -10,3 +10,3 @@ "types": "types/artplayer-plugin-danmuku.d.ts", | ||
"author": "Harvey Zack <laozhaochaguan@gmail.com>", | ||
"browserslist": "> 0.5%, last 2 versions, not dead", | ||
"browserslist": "last 1 Chrome version", | ||
"homepage": "https://artplayer.org", | ||
@@ -13,0 +13,0 @@ "repository": { |
@@ -9,8 +9,4 @@ # artplayer-plugin-danmuku | ||
## Usage | ||
[https://artplayer.org/document/en/Plugins/danmuku](https://artplayer.org/document/en/Plugins/danmuku) | ||
## License | ||
MIT © Harvey Zack |
@@ -6,6 +6,7 @@ export function getMode(key) { | ||
case 3: | ||
return 0; | ||
return 0; // 滚动 | ||
case 4: | ||
return 2; // 底部 | ||
case 5: | ||
return 1; | ||
return 1; // 顶部 | ||
default: | ||
@@ -49,6 +50,6 @@ return 0; | ||
export function bilibiliDanmuParseFromUrl(url) { | ||
return fetch(url) | ||
.then((res) => res.text()) | ||
.then((xmlString) => bilibiliDanmuParseFromXml(xmlString)); | ||
export async function bilibiliDanmuParseFromUrl(url) { | ||
const res = await fetch(url); | ||
const xmlString = await res.text(); | ||
return bilibiliDanmuParseFromXml(xmlString); | ||
} |
import { bilibiliDanmuParseFromUrl } from './bilibili'; | ||
import getDanmuTop from './getDanmuTop'; | ||
import workerText from 'bundle-text:./worker'; | ||
@@ -8,30 +8,39 @@ export default class Danmuku { | ||
this.utils = constructor.utils; | ||
this.validator = constructor.validator; | ||
this.$danmuku = template.$danmuku; | ||
this.$player = template.$player; | ||
this.utils = constructor.utils; // 工具库 | ||
this.validator = constructor.validator; // 配置校验器 | ||
this.$danmuku = template.$danmuku; // 弹幕层容器 | ||
this.$player = template.$player; // 播放器容器 | ||
this.art = art; | ||
this.danmus = []; | ||
this.queue = []; | ||
this.option = {}; | ||
this.$refs = []; | ||
this.isStop = false; | ||
this.isHide = false; | ||
this.timer = null; | ||
this.danmus = []; // 原始弹幕数据 | ||
this.queue = []; // 实际弹幕队列 | ||
this.option = {}; // 格式化后的配置项 | ||
this.$refs = []; // 弹幕DOM节点池 | ||
this.isStop = false; // 是否停止 | ||
this.isHide = false; // 是否隐藏 | ||
this.timer = null; // 定时器 | ||
this.index = 0; // 弹幕索引 | ||
// 弹幕状态池 | ||
this.states = { | ||
wait: [], | ||
ready: [], | ||
emit: [], | ||
stop: [], | ||
}; | ||
// 初始化配置 | ||
this.config(option); | ||
if (this.option.useWorker) { | ||
try { | ||
this.worker = new Worker(new URL('data-url:./worker.js', import.meta.url)); | ||
} catch (error) { | ||
// | ||
} | ||
} | ||
// 创建 Web Worker, 用于计算弹幕的 top 值 | ||
this.worker = new Worker(URL.createObjectURL(new Blob([workerText]))); | ||
// 绑定公用事件 | ||
this.start = this.start.bind(this); | ||
this.stop = this.stop.bind(this); | ||
this.reset = this.reset.bind(this); | ||
this.resize = this.resize.bind(this); | ||
this.destroy = this.destroy.bind(this); | ||
// 监听事件 | ||
art.on('video:play', this.start); | ||
@@ -41,32 +50,42 @@ art.on('video:playing', this.start); | ||
art.on('video:waiting', this.stop); | ||
art.on('resize', this.reset); | ||
art.on('destroy', this.destroy); | ||
art.on('resize', this.resize); | ||
// 开始加载弹幕 | ||
this.load(); | ||
} | ||
// 默认配置 | ||
static get option() { | ||
return { | ||
danmuku: [], | ||
speed: 5, | ||
margin: ['2%', '25%'], | ||
opacity: 1, | ||
color: '#FFFFFF', | ||
mode: 0, | ||
fontSize: 25, | ||
filter: () => true, | ||
antiOverlap: true, | ||
useWorker: true, | ||
synchronousPlayback: false, | ||
lockTime: 5, | ||
maxLength: 100, | ||
minWidth: 200, | ||
maxWidth: 400, | ||
mount: undefined, | ||
theme: 'dark', | ||
heatmap: false, | ||
beforeEmit: () => true, | ||
danmuku: [], // 弹幕数据 | ||
speed: 5, // 弹幕持续时间,范围在[1 ~ 10] | ||
margin: [10, '25%'], // 弹幕上下边距,支持像素数字和百分比 | ||
opacity: 1, // 弹幕透明度,范围在[0 ~ 1] | ||
color: '#FFFFFF', // 默认弹幕颜色,可以被单独弹幕项覆盖 | ||
mode: 0, // 默认弹幕模式: 0: 滚动,1: 顶部,2: 底部 | ||
modes: [0, 1, 2], // 弹幕可见的模式 | ||
fontSize: 25, // 弹幕字体大小,支持像素数字和百分比 | ||
antiOverlap: true, // 弹幕是否防重叠 | ||
synchronousPlayback: false, // 是否同步播放速度 | ||
mount: undefined, // 弹幕发射器挂载点, 默认为播放器控制栏中部 | ||
heatmap: false, // 是否开启热力图 | ||
points: [], // 热力图数据 | ||
filter: () => true, // 弹幕载入前的过滤器,只支持返回布尔值 | ||
beforeEmit: () => true, // 弹幕发送前的过滤器,支持返回 Promise | ||
beforeVisible: () => true, // 弹幕显示前的过滤器,支持返回 Promise | ||
visible: true, // 弹幕层是否可见 | ||
emitter: true, // 是否开启弹幕发射器 | ||
maxLength: 200, // 弹幕输入框最大长度, 范围在[1 ~ 1000] | ||
lockTime: 5, // 输入框锁定时间,范围在[1 ~ 60] | ||
theme: 'dark', // 弹幕主题,支持 dark 和 light,只在自定义挂载时生效 | ||
OPACITY: {}, // 不透明度配置项 | ||
FONT_SIZE: {}, // 弹幕字号配置项 | ||
MARGIN: {}, // 显示区域配置项 | ||
SPEED: {}, // 弹幕速度配置项 | ||
COLOR: [], // 颜色列表配置项 | ||
}; | ||
} | ||
// 配置校验 | ||
static get scheme() { | ||
@@ -80,22 +99,49 @@ return { | ||
mode: 'number', | ||
modes: 'array', | ||
fontSize: 'number|string', | ||
filter: 'function', | ||
antiOverlap: 'boolean', | ||
useWorker: 'boolean', | ||
synchronousPlayback: 'boolean', | ||
mount: '?htmldivelement|string', | ||
heatmap: 'object|boolean', | ||
points: 'array', | ||
filter: 'function', | ||
beforeEmit: 'function', | ||
beforeVisible: 'function', | ||
visible: 'boolean', | ||
emitter: 'boolean', | ||
maxLength: 'number', | ||
lockTime: 'number', | ||
maxLength: 'number', | ||
minWidth: 'number', | ||
maxWidth: 'number', | ||
mount: 'undefined|htmldivelement', | ||
theme: 'string', | ||
heatmap: 'object|boolean', | ||
beforeEmit: 'function', | ||
OPACITY: 'object', | ||
FONT_SIZE: 'object', | ||
MARGIN: 'object', | ||
SPEED: 'object', | ||
COLOR: 'array', | ||
}; | ||
} | ||
// 初始弹幕样式 | ||
static get cssText() { | ||
return ` | ||
user-select: none; | ||
position: absolute; | ||
white-space: pre; | ||
pointer-events: none; | ||
perspective: 500px; | ||
display: inline-block; | ||
will-change: transform; | ||
font-weight: normal; | ||
line-height: 1.125; | ||
visibility: hidden; | ||
font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif; | ||
text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px; | ||
`; | ||
} | ||
// 是否在移动端使用了自动旋屏,会影响弹幕的left和top值 | ||
get isRotate() { | ||
return this.art.plugins.autoOrientation && this.art.plugins.autoOrientation.state; | ||
return this.art.plugins?.autoOrientation?.state; | ||
} | ||
// 计算上空白边距 | ||
get marginTop() { | ||
@@ -118,2 +164,3 @@ const { clamp } = this.utils; | ||
// 计算下空白边距 | ||
get marginBottom() { | ||
@@ -136,46 +183,51 @@ const { clamp } = this.utils; | ||
filter(state, callback) { | ||
return this.queue.filter((danmu) => danmu.$state === state).map(callback); | ||
} | ||
// 计算弹幕字体大小 | ||
get fontSize() { | ||
const { clamp } = this.utils; | ||
const { clientHeight } = this.$player; | ||
getLeft($ref) { | ||
const rect = $ref.getBoundingClientRect(); | ||
return this.isRotate ? rect.top : rect.left; | ||
} | ||
const fontSize = this.option.fontSize; | ||
getRef() { | ||
const $refCache = this.$refs.pop(); | ||
if ($refCache) return $refCache; | ||
if (typeof fontSize === 'number') { | ||
return clamp(fontSize, 12, clientHeight); | ||
} | ||
const $ref = document.createElement('div'); | ||
if (typeof fontSize === 'string' && fontSize.endsWith('%')) { | ||
const ratio = parseFloat(fontSize) / 100; | ||
return clamp(clientHeight * ratio, 12, clientHeight); | ||
} | ||
$ref.style.cssText = ` | ||
user-select: none; | ||
position: absolute; | ||
white-space: pre; | ||
pointer-events: none; | ||
perspective: 500px; | ||
display: inline-block; | ||
will-change: transform; | ||
font-weight: normal; | ||
line-height: 1.125; | ||
visibility: hidden; | ||
font-family: SimHei, "Microsoft JhengHei", Arial, Helvetica, sans-serif; | ||
text-shadow: rgb(0, 0, 0) 1px 0px 1px, rgb(0, 0, 0) 0px 1px 1px, rgb(0, 0, 0) 0px -1px 1px, rgb(0, 0, 0) -1px 0px 1px; | ||
`; | ||
return Danmuku.option.fontSize; | ||
} | ||
// 获取弹幕DOM节点 | ||
get $ref() { | ||
const $ref = this.$refs.pop() || document.createElement('div'); | ||
$ref.style.cssText = Danmuku.cssText; | ||
$ref.dataset.mode = ''; | ||
$ref.className = ''; | ||
return $ref; | ||
} | ||
getReady() { | ||
// 获取准备好发送的弹幕 | ||
get readys() { | ||
const { currentTime } = this.art; | ||
return this.queue.filter((danmu) => { | ||
return ( | ||
danmu.$state === 'ready' || | ||
(danmu.$state === 'wait' && currentTime + 0.1 >= danmu.time && danmu.time >= currentTime - 0.1) | ||
); | ||
const result = []; | ||
// 有的是ready状态:之前因为弹幕太多而暂停发送的弹幕 | ||
this.filter('ready', (danmu) => result.push(danmu)); | ||
// 有的是wait状态:符合时间范围的弹幕 | ||
this.filter('wait', (danmu) => { | ||
if (currentTime + 0.1 >= danmu.time && danmu.time >= currentTime - 0.1) { | ||
result.push(danmu); | ||
} | ||
}); | ||
return result; | ||
} | ||
getEmits() { | ||
// 可见的弹幕的数据,用于计算下一个弹幕的top值 | ||
get visibles() { | ||
const result = []; | ||
@@ -211,37 +263,12 @@ const { clientWidth } = this.$player; | ||
getFontSize(fontSize) { | ||
const { clamp } = this.utils; | ||
const { clientHeight } = this.$player; | ||
if (typeof fontSize === 'number') { | ||
return clamp(fontSize, 12, clientHeight); | ||
} | ||
if (typeof fontSize === 'string' && fontSize.endsWith('%')) { | ||
const ratio = parseFloat(fontSize) / 100; | ||
return clamp(clientHeight * ratio, 12, clientHeight); | ||
} | ||
return Danmuku.option.fontSize; | ||
get speed() { | ||
return this.option.synchronousPlayback && this.art.playbackRate | ||
? this.option.speed / Number(this.art.playbackRate) | ||
: this.option.speed; | ||
} | ||
postMessage(message = {}) { | ||
return new Promise((resolve) => { | ||
if (this.option.useWorker && this.worker && this.worker.postMessage) { | ||
message.id = Date.now(); | ||
this.worker.postMessage(message); | ||
this.worker.onmessage = (event) => { | ||
const { data } = event; | ||
if (data.id === message.id) { | ||
resolve(data); | ||
} | ||
}; | ||
} else { | ||
const top = getDanmuTop(message); | ||
resolve({ top }); | ||
} | ||
}); | ||
} | ||
// 加载弹幕 | ||
async load() { | ||
const { errorHandle } = this.utils; | ||
async load() { | ||
try { | ||
@@ -258,8 +285,8 @@ if (typeof this.option.danmuku === 'function') { | ||
this.utils.errorHandle(Array.isArray(this.danmus), 'Danmuku need return an array as result'); | ||
this.art.emit('artplayerPluginDanmuku:loaded', this.danmus); | ||
errorHandle(Array.isArray(this.danmus), 'Danmuku need return an array as result'); | ||
this.queue = []; | ||
this.$danmuku.innerText = ''; | ||
this.danmus.forEach((danmu) => this.emit(danmu)); | ||
this.queue = []; // 清空实际弹幕队列 | ||
this.$danmuku.innerText = ''; // 清空弹幕层 | ||
this.danmus.forEach((danmu) => this.emit(danmu)); // 逐个验证原始弹幕并转换为实际弹幕 | ||
this.art.emit('artplayerPluginDanmuku:loaded', this.queue); | ||
} catch (error) { | ||
@@ -273,20 +300,105 @@ this.art.emit('artplayerPluginDanmuku:error', error); | ||
// 把原始弹幕转换为实际弹幕 | ||
emit(danmu) { | ||
const { clamp } = this.utils; | ||
this.validator(danmu, { | ||
text: 'string', // 弹幕文本 | ||
mode: '?number', // 弹幕模式: 0: 滚动,1: 顶部,2: 底部 | ||
color: '?string', // 弹幕颜色 | ||
time: '?number', // 弹幕时间 | ||
border: '?boolean', // 弹幕是否有边框 | ||
style: '?object', // 弹幕额外样式 | ||
}); | ||
// 弹幕文本为空则直接忽略 | ||
if (!danmu.text.trim()) return this; | ||
// 设置弹幕时间,如果没有则默认为当前时间加 0.5 秒 | ||
if (danmu.time) { | ||
danmu.time = clamp(danmu.time, 0, Infinity); | ||
} else { | ||
danmu.time = this.art.currentTime + 0.5; | ||
} | ||
// 设置弹幕模式,如果没有则默认为全局配置 | ||
if (danmu.mode === undefined) { | ||
danmu.mode = this.option.mode; | ||
} | ||
// 设置弹幕单独样式,如果没有则默认为空对象 | ||
if (danmu.style === undefined) { | ||
danmu.style = {}; | ||
} | ||
// 设置弹幕颜色,如果没有则默认为全局配置 | ||
if (danmu.color === undefined) { | ||
danmu.color = this.option.color; | ||
} | ||
// 弹幕模式只能是 0, 1, 2 | ||
if (![0, 1, 2].includes(danmu.mode)) return this; | ||
// 自定义弹幕过滤函数 | ||
if (!this.option.filter(danmu)) return this; | ||
// 添加自定义属性 | ||
const item = { | ||
...danmu, | ||
$state: 'wait', // 弹幕初始状态 | ||
$id: this.index++, // 弹幕唯一标识 | ||
$ref: null, // 弹幕 DOM 节点 | ||
$restTime: 0, // 弹幕剩余时间 | ||
$lastStartTime: 0, // 弹幕上次开始时间 | ||
}; | ||
// 转换为wait状态 | ||
this.setState(item, 'wait'); | ||
// 添加到实际弹幕队列 | ||
this.queue.push(item); | ||
// 弹幕有四个状态: | ||
// - wait: 弹幕还未开始显示,没有被添加到 DOM 中 | ||
// - ready: 弹幕准备好显示,没有被添加到 DOM 中 | ||
// - emit: 弹幕正在显示,已经被添加到 DOM 中 | ||
// - stop: 弹幕正在停止显示,已经被添加到 DOM 中 | ||
return this; | ||
} | ||
// 动态配置 | ||
config(option) { | ||
const { clamp } = this.utils; | ||
const { $controlsCenter } = this.art.template; | ||
// 判断配置项是否有变化 | ||
const changed = Object.keys(option).some( | ||
(key) => JSON.stringify(this.option[key]) !== JSON.stringify(option[key]), | ||
); | ||
if (!changed) return this; | ||
this.option = Object.assign({}, Danmuku.option, this.option, option); | ||
this.validator(this.option, Danmuku.scheme); | ||
this.option.mode = clamp(this.option.mode, 0, 2); | ||
this.option.speed = clamp(this.option.speed, 1, 10); | ||
this.option.opacity = clamp(this.option.opacity, 0, 1); | ||
this.option.lockTime = clamp(Math.floor(this.option.lockTime), 0, 60); | ||
this.option.maxLength = clamp(this.option.maxLength, 0, 500); | ||
this.option.minWidth = clamp(this.option.minWidth, 0, 500); | ||
this.option.maxWidth = clamp(this.option.maxWidth, 0, Infinity); | ||
this.option.lockTime = clamp(this.option.lockTime, 1, 60); | ||
this.option.maxLength = clamp(this.option.maxLength, 1, 1000); | ||
this.option.mount = this.option.mount || $controlsCenter; | ||
// 重新计算弹幕字体大小,需要重新渲染 | ||
if (option.fontSize) { | ||
this.option.fontSize = this.getFontSize(this.option.fontSize); | ||
this.reset(); | ||
} | ||
// 通过配置项控制弹幕的显示和隐藏 | ||
if (this.option.visible) { | ||
this.show(); | ||
} else { | ||
this.hide(); | ||
} | ||
this.art.emit('artplayerPluginDanmuku:config', this.option); | ||
@@ -297,5 +409,53 @@ | ||
// 计算DOM的left值,受到旋屏影响 | ||
getLeft($ref) { | ||
const rect = $ref.getBoundingClientRect(); | ||
return this.isRotate ? rect.top : rect.left; | ||
} | ||
// 计算弹幕的top值 | ||
postMessage(message = {}) { | ||
return new Promise((resolve) => { | ||
message.id = Date.now(); | ||
this.worker.postMessage(message); | ||
this.worker.onmessage = (event) => { | ||
const { data } = event; | ||
if (data.id === message.id) { | ||
resolve(data); | ||
} | ||
}; | ||
}); | ||
} | ||
// 根据状态获取弹幕 | ||
filter(state, callback) { | ||
const danmus = this.states[state] || []; | ||
for (let index = 0; index < danmus.length; index++) { | ||
callback(danmus[index]); | ||
} | ||
return danmus; | ||
} | ||
// 设置弹幕状态 | ||
setState(danmu, state) { | ||
// 从原状态池中删除 | ||
this.states[danmu.$state] = this.states[danmu.$state].filter((item) => item !== danmu); | ||
// 设置新状态 | ||
danmu.$state = state; | ||
// 设置DOM节点状态 | ||
if (danmu.$ref) { | ||
danmu.$ref.dataset.state = state; | ||
} | ||
// 添加到新状态池中 | ||
this.states[state].push(danmu); | ||
} | ||
// 重置弹幕到wait状态,回收弹幕DOM节点 | ||
makeWait(danmu) { | ||
danmu.$state = 'wait'; | ||
this.setState(danmu, 'wait'); | ||
if (danmu.$ref) { | ||
danmu.$ref.style.cssText = Danmuku.cssText; | ||
danmu.$ref.style.visibility = 'hidden'; | ||
@@ -310,11 +470,158 @@ danmu.$ref.style.marginLeft = '0px'; | ||
// 实时更新弹幕 | ||
update() { | ||
const { setStyles } = this.utils; | ||
this.timer = window.requestAnimationFrame(async () => { | ||
if (this.art.playing && !this.isHide) { | ||
// 实时计算弹幕的剩余显示时间 | ||
this.filter('emit', (danmu) => { | ||
const emitTime = (Date.now() - danmu.$lastStartTime) / 1000; | ||
danmu.$restTime -= emitTime; | ||
danmu.$lastStartTime = Date.now(); | ||
// 超过时间即重置弹幕 | ||
if (danmu.$restTime <= 0) { | ||
this.makeWait(danmu); | ||
} | ||
}); | ||
// 获取准备好发送的弹幕,可能包含ready和wait状态的弹幕 | ||
const readys = this.readys; | ||
for (let index = 0; index < readys.length; index++) { | ||
const danmu = readys[index]; | ||
// 弹幕发送前的过滤器 | ||
const state = await this.option.beforeVisible(danmu); | ||
if (state) { | ||
const { clientWidth, clientHeight } = this.$player; | ||
danmu.$ref = this.$ref; // 获取弹幕DOM节点 | ||
danmu.$ref.innerText = danmu.text; // 设置弹幕文本 | ||
// 提前添加到弹幕层中,用于计算top值 | ||
this.$danmuku.appendChild(danmu.$ref); | ||
// 设置初始弹幕样式 | ||
danmu.$ref.style.opacity = this.option.opacity; | ||
danmu.$ref.style.fontSize = `${this.fontSize}px`; | ||
danmu.$ref.style.color = danmu.color; | ||
danmu.$ref.style.border = danmu.border ? `1px solid ${danmu.color}` : null; | ||
danmu.$ref.style.backgroundColor = danmu.border ? 'rgb(0 0 0 / 50%)' : null; | ||
// 设置单独弹幕样式 | ||
setStyles(danmu.$ref, danmu.style); | ||
// 记录弹幕时间戳 | ||
danmu.$lastStartTime = Date.now(); | ||
// 计算弹幕剩余时间 | ||
danmu.$restTime = this.speed; | ||
// 计算弹幕滚动的距离 | ||
const distance = clientWidth + danmu.$ref.clientWidth; | ||
// 计算弹幕的top值 | ||
const { top } = await this.postMessage({ | ||
target: { | ||
mode: danmu.mode, | ||
height: danmu.$ref.clientHeight, | ||
speed: distance / danmu.$restTime, | ||
}, // 当前弹幕信息 | ||
visibles: this.visibles, // 可见的弹幕的数据 | ||
antiOverlap: this.option.antiOverlap, | ||
clientWidth: clientWidth, | ||
clientHeight: clientHeight, | ||
marginBottom: this.marginBottom, | ||
marginTop: this.marginTop, | ||
}); | ||
if (danmu.$ref) { | ||
if (!this.isStop && top !== undefined) { | ||
this.setState(danmu, 'emit'); // 转换为emit状态 | ||
danmu.$ref.style.top = `${top}px`; | ||
danmu.$ref.style.visibility = 'visible'; | ||
danmu.$ref.dataset.mode = danmu.mode; // CSS控制模式的显示和隐藏 | ||
switch (danmu.mode) { | ||
// 滚动的弹幕 | ||
case 0: { | ||
danmu.$ref.style.left = `${clientWidth}px`; | ||
danmu.$ref.style.marginLeft = '0px'; | ||
danmu.$ref.style.transform = `translateX(${-distance}px)`; | ||
danmu.$ref.style.transition = `transform ${danmu.$restTime}s linear 0s`; | ||
break; | ||
} | ||
case 1: | ||
// falls through | ||
case 2: | ||
danmu.$ref.style.left = '50%'; | ||
danmu.$ref.style.marginLeft = `-${danmu.$ref.clientWidth / 2}px`; | ||
break; | ||
default: | ||
break; | ||
} | ||
this.art.emit('artplayerPluginDanmuku:visible', danmu); | ||
} else { | ||
// 假如弹幕已经停止或者没有 top 值,则重置弹幕为ready状态,回收弹幕DOM节点,等待下次发送 | ||
this.setState(danmu, 'ready'); | ||
this.$refs.push(danmu.$ref); | ||
danmu.$ref = null; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
// 递归调用 | ||
if (!this.isStop) { | ||
this.update(); | ||
} | ||
}); | ||
return this; | ||
} | ||
// 重置正在显示的弹幕: stop/emit 状态的弹幕 | ||
resize() { | ||
const { clientWidth } = this.$player; | ||
this.filter('stop', (danmu) => { | ||
switch (danmu.mode) { | ||
// 滚动的弹幕 | ||
case 0: | ||
danmu.$ref.style.left = `${clientWidth}px`; | ||
break; | ||
default: | ||
break; | ||
} | ||
}); | ||
this.filter('emit', (danmu) => { | ||
danmu.$lastStartTime = Date.now(); | ||
switch (danmu.mode) { | ||
// 滚动的弹幕 | ||
case 0: { | ||
const distance = clientWidth + danmu.$ref.clientWidth; | ||
danmu.$ref.style.left = `${clientWidth}px`; | ||
danmu.$ref.style.transform = `translateX(${-distance}px)`; | ||
danmu.$ref.style.transition = `transform ${danmu.$restTime}s linear 0s`; | ||
break; | ||
} | ||
default: | ||
break; | ||
} | ||
}); | ||
} | ||
// 继续弹幕 | ||
continue() { | ||
const { clientWidth } = this.$player; | ||
this.filter('stop', (danmu) => { | ||
danmu.$state = 'emit'; | ||
this.setState(danmu, 'emit'); // 转换为emit状态 | ||
danmu.$lastStartTime = Date.now(); | ||
switch (danmu.mode) { | ||
// 继续滚动的弹幕 | ||
case 0: { | ||
const translateX = clientWidth + danmu.$ref.clientWidth; | ||
danmu.$ref.style.transform = `translateX(${-translateX}px)`; | ||
const distance = clientWidth + danmu.$ref.clientWidth; | ||
danmu.$ref.style.transform = `translateX(${-distance}px)`; | ||
danmu.$ref.style.transition = `transform ${danmu.$restTime}s linear 0s`; | ||
@@ -331,7 +638,9 @@ break; | ||
// 暂停弹幕 | ||
suspend() { | ||
const { clientWidth } = this.$player; | ||
this.filter('emit', (danmu) => { | ||
danmu.$state = 'stop'; | ||
this.setState(danmu, 'stop'); // 转换为stop状态 | ||
switch (danmu.mode) { | ||
// 停止滚动的弹幕 | ||
case 0: { | ||
@@ -351,94 +660,2 @@ const translateX = clientWidth - (this.getLeft(danmu.$ref) - this.getLeft(this.$player)); | ||
reset() { | ||
this.queue.forEach((danmu) => this.makeWait(danmu)); | ||
return this; | ||
} | ||
update() { | ||
this.timer = window.requestAnimationFrame(async () => { | ||
if (this.art.playing && !this.isHide) { | ||
this.filter('emit', (danmu) => { | ||
const emitTime = (Date.now() - danmu.$lastStartTime) / 1000; | ||
danmu.$restTime -= emitTime; | ||
danmu.$lastStartTime = Date.now(); | ||
if (danmu.$restTime <= 0) { | ||
this.makeWait(danmu); | ||
} | ||
}); | ||
const readys = this.getReady(); | ||
const { clientWidth, clientHeight } = this.$player; | ||
for (let index = 0; index < readys.length; index++) { | ||
const danmu = readys[index]; | ||
danmu.$ref = this.getRef(); | ||
danmu.$ref.innerText = danmu.text; | ||
this.$danmuku.appendChild(danmu.$ref); | ||
danmu.$ref.style.left = `${clientWidth}px`; | ||
danmu.$ref.style.opacity = this.option.opacity; | ||
danmu.$ref.style.fontSize = `${this.option.fontSize}px`; | ||
danmu.$ref.style.color = danmu.color; | ||
danmu.$ref.style.border = danmu.border ? `1px solid ${danmu.color}` : null; | ||
danmu.$ref.style.backgroundColor = danmu.border ? 'rgb(0 0 0 / 50%)' : null; | ||
danmu.$ref.style.marginLeft = '0px'; | ||
danmu.$lastStartTime = Date.now(); | ||
danmu.$restTime = | ||
this.option.synchronousPlayback && this.art.playbackRate | ||
? this.option.speed / Number(this.art.playbackRate) | ||
: this.option.speed; | ||
const target = { | ||
mode: danmu.mode, | ||
height: danmu.$ref.clientHeight, | ||
speed: (clientWidth + danmu.$ref.clientWidth) / danmu.$restTime, | ||
}; | ||
const { top } = await this.postMessage({ | ||
target, | ||
emits: this.getEmits(), | ||
antiOverlap: this.option.antiOverlap, | ||
clientWidth: clientWidth, | ||
clientHeight: clientHeight, | ||
marginBottom: this.marginBottom, | ||
marginTop: this.marginTop, | ||
}); | ||
if (danmu.$ref) { | ||
if (!this.isStop && top !== undefined) { | ||
danmu.$state = 'emit'; | ||
danmu.$ref.style.visibility = 'visible'; | ||
switch (danmu.mode) { | ||
case 0: { | ||
danmu.$ref.style.top = `${top}px`; | ||
const translateX = clientWidth + danmu.$ref.clientWidth; | ||
danmu.$ref.style.transform = `translateX(${-translateX}px)`; | ||
danmu.$ref.style.transition = `transform ${danmu.$restTime}s linear 0s`; | ||
break; | ||
} | ||
case 1: | ||
danmu.$ref.style.left = '50%'; | ||
danmu.$ref.style.top = `${top}px`; | ||
danmu.$ref.style.marginLeft = `-${danmu.$ref.clientWidth / 2}px`; | ||
break; | ||
default: | ||
break; | ||
} | ||
} else { | ||
danmu.$state = 'ready'; | ||
this.$refs.push(danmu.$ref); | ||
danmu.$ref = null; | ||
} | ||
} | ||
} | ||
} | ||
if (!this.isStop) { | ||
this.update(); | ||
} | ||
}); | ||
return this; | ||
} | ||
stop() { | ||
@@ -460,6 +677,12 @@ this.isStop = true; | ||
reset() { | ||
this.queue.forEach((danmu) => this.makeWait(danmu)); | ||
this.art.emit('artplayerPluginDanmuku:reset'); | ||
return this; | ||
} | ||
show() { | ||
this.isHide = false; | ||
this.start(); | ||
this.$danmuku.style.display = 'block'; | ||
this.$danmuku.style.opacity = 1; | ||
this.option.visible = true; | ||
this.art.emit('artplayerPluginDanmuku:show'); | ||
@@ -471,5 +694,4 @@ return this; | ||
this.isHide = true; | ||
this.stop(); | ||
this.queue.forEach((item) => this.makeWait(item)); | ||
this.$danmuku.style.display = 'none'; | ||
this.$danmuku.style.opacity = 0; | ||
this.option.visible = false; | ||
this.art.emit('artplayerPluginDanmuku:hide'); | ||
@@ -479,42 +701,5 @@ return this; | ||
emit(danmu) { | ||
this.validator(danmu, { | ||
text: 'string', | ||
mode: 'number|undefined', | ||
color: 'string|undefined', | ||
time: 'number|undefined', | ||
border: 'boolean|undefined', | ||
}); | ||
if (!danmu.text.trim()) return this; | ||
if (!this.option.filter(danmu)) return this; | ||
if (danmu.time) { | ||
danmu.time = this.utils.clamp(danmu.time, 0, Infinity); | ||
} else { | ||
danmu.time = this.art.currentTime + 0.5; | ||
} | ||
if (danmu.mode === undefined) { | ||
danmu.mode = this.option.mode; | ||
} | ||
if (danmu.color === undefined) { | ||
danmu.color = this.option.color; | ||
} | ||
this.queue.push({ | ||
...danmu, | ||
$state: 'wait', | ||
$ref: null, | ||
$restTime: 0, | ||
$lastStartTime: 0, | ||
}); | ||
return this; | ||
} | ||
destroy() { | ||
this.stop(); | ||
if (this.worker && this.worker.terminate) this.worker.terminate(); | ||
this.worker.terminate(); | ||
this.art.off('video:play', this.start); | ||
@@ -521,0 +706,0 @@ this.art.off('video:playing', this.start); |
@@ -47,3 +47,3 @@ const lib = { | ||
function update() { | ||
function update(arg = []) { | ||
$start = null; | ||
@@ -53,3 +53,3 @@ $stop = null; | ||
if (!danmuku.danmus.length || !art.duration) return; | ||
if (!art.duration || art.option.isLive) return; | ||
@@ -78,11 +78,18 @@ const svg = { | ||
const points = []; | ||
const gap = art.duration / svg.w; | ||
for (let x = 0; x <= svg.w; x += options.sampling) { | ||
const y = danmuku.danmus.filter( | ||
({ time }) => time > x * gap && time <= (x + options.sampling) * gap, | ||
).length; | ||
points.push([x, y]); | ||
let points = []; | ||
if (Array.isArray(arg) && arg.length) { | ||
points = [...arg]; | ||
} else { | ||
const gap = art.duration / svg.w; | ||
for (let x = 0; x <= svg.w; x += options.sampling) { | ||
const y = danmuku.danmus.filter( | ||
({ time }) => time > x * gap && time <= (x + options.sampling) * gap, | ||
).length; | ||
points.push([x, y]); | ||
} | ||
} | ||
if (points.length === 0) return; | ||
const lastPoint = points[points.length - 1]; | ||
@@ -173,7 +180,8 @@ const lastX = lastPoint[0]; | ||
art.on('ready', update); | ||
art.on('resize', update); | ||
art.on('artplayerPluginDanmuku:loaded', update); | ||
art.on('ready', () => update()); | ||
art.on('resize', () => update()); | ||
art.on('artplayerPluginDanmuku:loaded', () => update()); | ||
art.on('artplayerPluginDanmuku:points', (points) => update(points)); | ||
}, | ||
}); | ||
} |
import Danmuku from './danmuku'; | ||
import setting from './setting'; | ||
import Setting from './setting'; | ||
import heatmap from './heatmap'; | ||
function checkVersion(art) { | ||
const { | ||
version, | ||
utils: { errorHandle }, | ||
} = art.constructor; | ||
const arr = version.split('.').map(Number); | ||
const major = arr[0]; | ||
const minor = arr[1] / 100; | ||
errorHandle(major + minor >= 5, `Artplayer.js@${version} 不兼容该弹幕库,请更新到 Artplayer.js@5.x.x 版本以上`); | ||
} | ||
export default function artplayerPluginDanmuku(option) { | ||
return (art) => { | ||
checkVersion(art); | ||
const danmuku = new Danmuku(art, option); | ||
setting(art, danmuku); | ||
if (option.heatmap && !art.option.isLive) { | ||
heatmap(art, danmuku, option.heatmap); | ||
const setting = new Setting(art, danmuku); | ||
if (danmuku.option.heatmap) { | ||
heatmap(art, danmuku, danmuku.option.heatmap); | ||
} | ||
return { | ||
@@ -32,2 +22,3 @@ name: 'artplayerPluginDanmuku', | ||
reset: danmuku.reset.bind(danmuku), | ||
mount: setting.mount.bind(setting), | ||
get option() { | ||
@@ -46,5 +37,3 @@ return danmuku.option; | ||
artplayerPluginDanmuku.env = process.env.NODE_ENV; | ||
artplayerPluginDanmuku.version = process.env.APP_VER; | ||
artplayerPluginDanmuku.build = process.env.BUILD_DATE; | ||
artplayerPluginDanmuku.icons = Setting.icons; | ||
@@ -51,0 +40,0 @@ if (typeof window !== 'undefined') { |
import style from 'bundle-text:./style.less'; | ||
import danmuOn from 'bundle-text:./img/danmu-on.svg'; | ||
import danmuOff from 'bundle-text:./img/danmu-off.svg'; | ||
import danmuConfig from 'bundle-text:./img/danmu-config.svg'; | ||
import danmuStyle from 'bundle-text:./img/danmu-style.svg'; | ||
import $on from 'bundle-text:./img/on.svg'; | ||
import $off from 'bundle-text:./img/off.svg'; | ||
import $config from 'bundle-text:./img/config.svg'; | ||
import $style from 'bundle-text:./img/style.svg'; | ||
import $mode_0_off from 'bundle-text:./img/mode_0_off.svg'; | ||
import $mode_0_on from 'bundle-text:./img/mode_0_on.svg'; | ||
import $mode_1_off from 'bundle-text:./img/mode_1_off.svg'; | ||
import $mode_1_on from 'bundle-text:./img/mode_1_on.svg'; | ||
import $mode_2_off from 'bundle-text:./img/mode_2_off.svg'; | ||
import $mode_2_on from 'bundle-text:./img/mode_2_on.svg'; | ||
import $check_on from 'bundle-text:./img/check_on.svg'; | ||
import $check_off from 'bundle-text:./img/check_off.svg'; | ||
export default function setting(art, danmuku) { | ||
const { option } = danmuku; | ||
const { | ||
template: { $controlsCenter, $player }, | ||
constructor: { | ||
SETTING_ITEM_WIDTH, | ||
utils: { removeClass, addClass, append, setStyle, tooltip, query, inverseClass, getIcon }, | ||
}, | ||
} = art; | ||
export default class Setting { | ||
constructor(art, danmuku) { | ||
this.art = art; | ||
this.danmuku = danmuku; | ||
this.utils = art.constructor.utils; | ||
setStyle($controlsCenter, 'display', 'flex'); | ||
const { setStyle } = this.utils; | ||
const { $controlsCenter } = art.template; | ||
setStyle($controlsCenter, 'display', 'flex'); | ||
const $danmuOn = getIcon('danmu-on', danmuOn); | ||
const $danmuOff = getIcon('danmu-off', danmuOff); | ||
const $danmuConfig = getIcon('danmu-config', danmuConfig); | ||
const $danmuStyle = getIcon('danmu-style', danmuStyle); | ||
this.template = { | ||
$controlsCenter, | ||
$mount: $controlsCenter, | ||
$danmuku: null, | ||
$toggle: null, | ||
$configModes: null, | ||
$styleModes: null, | ||
$colors: null, | ||
$opacitySlider: null, | ||
$opacityValue: null, | ||
$marginSlider: null, | ||
$marginValue: null, | ||
$fontSizeSlider: null, | ||
$fontSizeValue: null, | ||
$speedSlider: null, | ||
$speedValue: null, | ||
$input: null, | ||
$send: null, | ||
}; | ||
function addEmitter() { | ||
const colors = [ | ||
'#FE0302', | ||
'#FF7204', | ||
'#FFAA02', | ||
'#FFD302', | ||
'#FFFF00', | ||
'#A0EE00', | ||
'#00CD00', | ||
'#019899', | ||
'#4266BE', | ||
'#89D5FF', | ||
'#CC0273', | ||
'#222222', | ||
'#9B9B9B', | ||
'#FFFFFF', | ||
].map((item) => { | ||
const isCurrent = option.color === item ? ' art-current' : ''; | ||
return `<div class="art-danmuku-style-panel-color${isCurrent}" data-color="${item}" style="background-color:${item}"></div>`; | ||
}); | ||
this.slider = { | ||
opacity: null, | ||
margin: null, | ||
fontSize: null, | ||
speed: null, | ||
}; | ||
const $emitter = append( | ||
$controlsCenter, | ||
` | ||
<div class="art-danmuku-emitter" style="max-width: ${option.maxWidth ? `${option.maxWidth}px` : '100%'}"> | ||
<div class="art-danmuku-left"> | ||
<div class="art-danmuku-style"> | ||
<div class="art-danmuku-style-panel"> | ||
<div class="art-danmuku-style-panel-inner"> | ||
<div class="art-danmuku-style-panel-title">模式</div> | ||
<div class="art-danmuku-style-panel-modes"> | ||
<div class="art-danmuku-style-panel-mode art-current" data-mode="0">滚动</div> | ||
<div class="art-danmuku-style-panel-mode" data-mode="1">静止</div> | ||
this.emitting = false; | ||
this.isLock = false; | ||
this.timer = null; | ||
this.createTemplate(); | ||
this.createSliders(); | ||
this.createEvents(); | ||
this.mount(this.option.mount); | ||
art.on('fullscreen', (state) => this.onFullscreen(state)); | ||
art.on('fullscreenWeb', (state) => this.onFullscreen(state)); | ||
} | ||
static get icons() { | ||
return { | ||
$on, | ||
$off, | ||
$config, | ||
$style, | ||
$mode_0_off, | ||
$mode_0_on, | ||
$mode_1_off, | ||
$mode_1_on, | ||
$mode_2_off, | ||
$mode_2_on, | ||
$check_on, | ||
$check_off, | ||
}; | ||
} | ||
get option() { | ||
return this.danmuku.option; | ||
} | ||
get outside() { | ||
return this.template.$mount !== this.template.$controlsCenter; | ||
} | ||
get TEMPLATE() { | ||
const { option } = this; | ||
return ` | ||
<div class="apd-toggle"> | ||
${$on}${$off} | ||
</div> | ||
<div class="apd-config"> | ||
${$config} | ||
<div class="apd-config-panel"> | ||
<div class="apd-config-panel-inner"> | ||
<div class="apd-config-mode"> | ||
按类型屏蔽 | ||
<div class="apd-modes"> | ||
<div data-mode="0" class="apd-mode"> | ||
${$mode_0_off}${$mode_0_on} | ||
<div>滚动</div> | ||
</div> | ||
<div class="art-danmuku-style-panel-title">颜色</div> | ||
<div class="art-danmuku-style-panel-colors"> | ||
${colors.join('')} | ||
<div data-mode="1" class="apd-mode"> | ||
${$mode_1_off}${$mode_1_on} | ||
<div>顶部</div> | ||
</div> | ||
<div data-mode="2" class="apd-mode"> | ||
${$mode_2_off}${$mode_2_on} | ||
<div>底部</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="apd-config-other"> | ||
<div class="apd-other apd-anti-overlap"> | ||
${$check_on}${$check_off} | ||
防止弹幕重叠 | ||
</div> | ||
<div class="apd-other apd-sync-video"> | ||
${$check_on}${$check_off} | ||
同步视频速度 | ||
</div> | ||
</div> | ||
<div class="apd-config-slider apd-config-opacity"> | ||
不透明度 | ||
<div class="apd-slider"></div> | ||
<div class="apd-value">未知</div> | ||
</div> | ||
<div class="apd-config-slider apd-config-margin"> | ||
显示区域 | ||
<div class="apd-slider"></div> | ||
<div class="apd-value">未知</div> | ||
</div> | ||
<div class="apd-config-slider apd-config-fontSize"> | ||
弹幕字号 | ||
<div class="apd-slider"></div> | ||
<div class="apd-value">未知</div> | ||
</div> | ||
<div class="apd-config-slider apd-config-speed"> | ||
弹幕速度 | ||
<div class="apd-slider"></div> | ||
<div class="apd-value">未知</div> | ||
</div> | ||
</div> | ||
<input class="art-danmuku-input" maxlength="${option.maxLength}" placeholder="发个弹幕见证当下" /> | ||
</div> | ||
<div class="art-danmuku-send">发送</div> | ||
</div> | ||
`, | ||
); | ||
<div class="apd-emitter"> | ||
<div class="apd-style"> | ||
${$style} | ||
<div class="apd-style-panel"> | ||
<div class="apd-style-panel-inner"> | ||
<div class="apd-style-mode"> | ||
模式 | ||
<div class="apd-modes"> | ||
<div data-mode="0" class="apd-mode"> | ||
${$mode_0_on} | ||
<div>滚动</div> | ||
</div> | ||
<div data-mode="1" class="apd-mode"> | ||
${$mode_1_on} | ||
<div>顶部</div> | ||
</div> | ||
<div data-mode="2" class="apd-mode"> | ||
${$mode_2_on} | ||
<div>底部</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="apd-style-color"> | ||
颜色 | ||
<div class="apd-colors"> | ||
${this.COLOR.map((color) => `<div data-color="${color}" class="apd-color" style="background-color: ${color}"></div>`).join('')} | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<input class="apd-input" placeholder="发个友善的弹幕见证当下" autocomplete="off" maxLength="${option.maxLength}" /> | ||
<div class="apd-send">发送</div> | ||
</div> | ||
`; | ||
} | ||
const $style = query('.art-danmuku-style', $emitter); | ||
const $input = query('.art-danmuku-input', $emitter); | ||
const $send = query('.art-danmuku-send', $emitter); | ||
const $panel = query('.art-danmuku-style-panel-inner', $emitter); | ||
const $modes = query('.art-danmuku-style-panel-modes', $emitter); | ||
const $colors = query('.art-danmuku-style-panel-colors', $emitter); | ||
const $layer = option.mount || append($player, '<div class="art-layer-danmuku-emitter"></div>'); | ||
get OPACITY() { | ||
return { | ||
min: 0, | ||
max: 100, | ||
steps: [], | ||
...this.option.OPACITY, | ||
}; | ||
} | ||
if (art.option.backdrop) { | ||
addClass($panel, 'art-backdrop-filter'); | ||
} | ||
get FONT_SIZE() { | ||
return { | ||
min: 12, | ||
max: 120, | ||
steps: [], | ||
...this.option.FONT_SIZE, | ||
}; | ||
} | ||
if (option.theme) { | ||
addClass($emitter, `art-danmuku-theme-${option.theme}`); | ||
get MARGIN() { | ||
return { | ||
min: 0, | ||
max: 3, | ||
steps: [ | ||
{ | ||
name: '1/4', | ||
value: [10, '75%'], | ||
}, | ||
{ | ||
name: '半屏', | ||
value: [10, '50%'], | ||
}, | ||
{ | ||
name: '3/4', | ||
value: [10, '25%'], | ||
}, | ||
{ | ||
name: '满屏', | ||
value: [10, 10], | ||
}, | ||
], | ||
...this.option.MARGIN, | ||
}; | ||
} | ||
get SPEED() { | ||
return { | ||
min: 0, | ||
max: 4, | ||
steps: [ | ||
{ | ||
name: '极慢', | ||
value: 10, | ||
}, | ||
{ | ||
name: '较慢', | ||
value: 7.5, | ||
hide: true, | ||
}, | ||
{ | ||
name: '适中', | ||
value: 5, | ||
}, | ||
{ | ||
name: '较快', | ||
value: 2.5, | ||
hide: true, | ||
}, | ||
{ | ||
name: '极快', | ||
value: 1, | ||
}, | ||
], | ||
...this.option.SPEED, | ||
}; | ||
} | ||
get COLOR() { | ||
return this.option.COLOR.length | ||
? this.option.COLOR | ||
: [ | ||
'#FE0302', | ||
'#FF7204', | ||
'#FFAA02', | ||
'#FFD302', | ||
'#FFFF00', | ||
'#A0EE00', | ||
'#00CD00', | ||
'#019899', | ||
'#4266BE', | ||
'#89D5FF', | ||
'#CC0273', | ||
'#222222', | ||
'#9B9B9B', | ||
'#FFFFFF', | ||
]; | ||
} | ||
query(selector) { | ||
const { query } = this.utils; | ||
const { $danmuku } = this.template; | ||
return query(selector, $danmuku); | ||
} | ||
setData(key, value) { | ||
const { $player } = this.art.template; | ||
const { $mount } = this.template; | ||
$player.dataset[key] = value; | ||
if (this.outside) { | ||
$mount.dataset[key] = value; | ||
} | ||
} | ||
let timer = null; | ||
let mode = option.mode; | ||
let color = option.color; | ||
append($style, $danmuStyle); | ||
createTemplate() { | ||
const { createElement, tooltip } = this.utils; | ||
function countdown(time) { | ||
if (time <= 0) { | ||
timer = null; | ||
$send.innerText = '发送'; | ||
removeClass($send, 'art-disabled'); | ||
const $danmuku = createElement('div'); | ||
$danmuku.className = 'artplayer-plugin-danmuku'; | ||
$danmuku.innerHTML = this.TEMPLATE; | ||
this.template.$danmuku = $danmuku; | ||
this.template.$toggle = this.query('.apd-toggle'); | ||
this.template.$configModes = this.query('.apd-config-mode .apd-modes'); | ||
this.template.$styleModes = this.query('.apd-style-mode .apd-modes'); | ||
this.template.$colors = this.query('.apd-colors'); | ||
this.template.$antiOverlap = this.query('.apd-anti-overlap'); | ||
this.template.$syncVideo = this.query('.apd-sync-video'); | ||
this.template.$opacitySlider = this.query('.apd-config-opacity .apd-slider'); | ||
this.template.$opacityValue = this.query('.apd-config-opacity .apd-value'); | ||
this.template.$marginSlider = this.query('.apd-config-margin .apd-slider'); | ||
this.template.$marginValue = this.query('.apd-config-margin .apd-value'); | ||
this.template.$fontSizeSlider = this.query('.apd-config-fontSize .apd-slider'); | ||
this.template.$fontSizeValue = this.query('.apd-config-fontSize .apd-value'); | ||
this.template.$speedSlider = this.query('.apd-config-speed .apd-slider'); | ||
this.template.$speedValue = this.query('.apd-config-speed .apd-value'); | ||
this.template.$input = this.query('.apd-input'); | ||
this.template.$send = this.query('.apd-send'); | ||
const { $toggle } = this.template; | ||
this.art.on('artplayerPluginDanmuku:show', () => { | ||
tooltip($toggle, '关闭弹幕'); | ||
}); | ||
this.art.on('artplayerPluginDanmuku:hide', () => { | ||
tooltip($toggle, '打开弹幕'); | ||
}); | ||
} | ||
createEvents() { | ||
const { $toggle, $configModes, $styleModes, $colors, $antiOverlap, $syncVideo, $send, $input } = this.template; | ||
this.art.proxy($toggle, 'click', () => { | ||
this.danmuku.config({ | ||
visible: !this.option.visible, | ||
}); | ||
this.reset(); | ||
}); | ||
this.art.proxy($configModes, 'click', (event) => { | ||
const $mode = event.target.closest('.apd-mode'); | ||
if (!$mode) return; | ||
const mode = Number($mode.dataset.mode); | ||
if (this.option.modes.includes(mode)) { | ||
this.danmuku.config({ | ||
modes: this.option.modes.filter((m) => m !== mode), | ||
}); | ||
} else { | ||
$send.innerText = time; | ||
timer = setTimeout(() => countdown(time - 1), 1000); | ||
this.danmuku.config({ | ||
modes: [...this.option.modes, mode], | ||
}); | ||
} | ||
} | ||
this.reset(); | ||
}); | ||
function onSend() { | ||
const danmu = { | ||
mode, | ||
color, | ||
border: true, | ||
text: $input.value.trim(), | ||
}; | ||
this.art.proxy($antiOverlap, 'click', () => { | ||
this.danmuku.config({ | ||
antiOverlap: !this.option.antiOverlap, | ||
}); | ||
this.reset(); | ||
}); | ||
if (timer === null && option.beforeEmit(danmu)) { | ||
$input.value = ''; | ||
danmuku.emit(danmu); | ||
addClass($send, 'art-disabled'); | ||
countdown(option.lockTime); | ||
art.emit('artplayerPluginDanmuku:emit', danmu); | ||
} | ||
} | ||
this.art.proxy($syncVideo, 'click', () => { | ||
this.danmuku.config({ | ||
synchronousPlayback: !this.option.synchronousPlayback, | ||
}); | ||
this.reset(); | ||
}); | ||
function onResize() { | ||
if ($controlsCenter.clientWidth < option.minWidth) { | ||
append($layer, $emitter); | ||
setStyle($layer, 'display', 'flex'); | ||
addClass($emitter, 'art-danmuku-mount'); | ||
this.art.proxy($styleModes, 'click', (event) => { | ||
const $mode = event.target.closest('.apd-mode'); | ||
if (!$mode) return; | ||
const mode = Number($mode.dataset.mode); | ||
this.danmuku.config({ | ||
mode: mode, | ||
}); | ||
this.reset(); | ||
}); | ||
if (!option.mount) { | ||
setStyle($player, 'marginBottom', '40px'); | ||
} | ||
} else { | ||
append($controlsCenter, $emitter); | ||
setStyle($layer, 'display', 'none'); | ||
removeClass($emitter, 'art-danmuku-mount'); | ||
this.art.proxy($colors, 'click', (event) => { | ||
const $color = event.target.closest('.apd-color'); | ||
if (!$color) return; | ||
this.danmuku.config({ | ||
color: $color.dataset.color, | ||
}); | ||
this.reset(); | ||
}); | ||
if (!option.mount) { | ||
setStyle($player, 'marginBottom', null); | ||
} | ||
} | ||
} | ||
this.art.proxy($send, 'click', () => this.emit()); | ||
art.proxy($send, 'click', onSend); | ||
art.proxy($input, 'keypress', (event) => { | ||
this.art.proxy($input, 'keypress', (event) => { | ||
if (event.key === 'Enter') { | ||
event.preventDefault(); | ||
onSend(); | ||
this.emit(); | ||
} | ||
}); | ||
} | ||
art.proxy($modes, 'click', (event) => { | ||
const { dataset } = event.target; | ||
if (dataset.mode) { | ||
mode = Number(dataset.mode); | ||
inverseClass(event.target, 'art-current'); | ||
} | ||
createSliders() { | ||
this.slider.opacity = this.createSlider({ | ||
...this.OPACITY, | ||
container: this.template.$opacitySlider, | ||
findIndex: () => { | ||
return Math.round(this.option.opacity * 100); | ||
}, | ||
onChange: (index) => { | ||
const { $opacityValue } = this.template; | ||
$opacityValue.textContent = `${index}%`; | ||
this.danmuku.config({ | ||
opacity: index / 100, | ||
}); | ||
}, | ||
}); | ||
art.proxy($colors, 'click', (event) => { | ||
const { dataset } = event.target; | ||
if (dataset.color) { | ||
color = dataset.color; | ||
inverseClass(event.target, 'art-current'); | ||
this.slider.margin = this.createSlider({ | ||
...this.MARGIN, | ||
container: this.template.$marginSlider, | ||
findIndex: () => { | ||
return this.MARGIN.steps.findIndex( | ||
(item) => item.value[0] === this.option.margin[0] && item.value[1] === this.option.margin[1], | ||
); | ||
}, | ||
onChange: (index) => { | ||
const margin = this.MARGIN.steps[index]; | ||
if (!margin) return; | ||
const { $marginValue } = this.template; | ||
$marginValue.textContent = margin.name; | ||
this.danmuku.config({ | ||
margin: margin.value, | ||
}); | ||
}, | ||
}); | ||
this.slider.fontSize = this.createSlider({ | ||
...this.FONT_SIZE, | ||
container: this.template.$fontSizeSlider, | ||
findIndex: () => { | ||
return Math.round(this.danmuku.fontSize); | ||
}, | ||
onChange: (index) => { | ||
const { $fontSizeValue } = this.template; | ||
$fontSizeValue.textContent = `${index}px`; | ||
this.danmuku.config({ | ||
fontSize: index, | ||
}); | ||
}, | ||
}); | ||
this.slider.speed = this.createSlider({ | ||
...this.SPEED, | ||
container: this.template.$speedSlider, | ||
findIndex: () => { | ||
return this.SPEED.steps.findIndex((item) => item.value === this.option.speed); | ||
}, | ||
onChange: (index) => { | ||
const speed = this.SPEED.steps[index]; | ||
if (!speed) return; | ||
const { $speedValue } = this.template; | ||
$speedValue.textContent = speed.name; | ||
this.danmuku.config({ | ||
speed: speed.value, | ||
}); | ||
}, | ||
}); | ||
} | ||
createSlider({ min, max, container, findIndex, onChange, steps = [] }) { | ||
const { query, clamp } = this.utils; | ||
container.innerHTML = ` | ||
<div class="apd-slider-line"> | ||
<div class="apd-slider-points"> | ||
${steps.map(() => `<div class="apd-slider-point"></div>`).join('')} | ||
</div> | ||
<div class="apd-slider-progress"></div> | ||
</div> | ||
<div class="apd-slider-dot"></div> | ||
<div class="apd-slider-steps"> | ||
${steps.map((step) => (step.hide ? '' : `<div class="apd-slider-step">${step.name}</div>`)).join('')} | ||
</div> | ||
`; | ||
const $dot = query('.apd-slider-dot', container); | ||
const $progress = query('.apd-slider-progress', container); | ||
let isDroging = false; | ||
function reset(index = findIndex()) { | ||
if (index < min || index > max) return; | ||
const percentage = (index - min) / (max - min); | ||
$dot.style.left = `${percentage * 100}%`; | ||
if (steps.length === 0) { | ||
$progress.style.width = $dot.style.left; | ||
} | ||
onChange(index); | ||
} | ||
function updateLeft(event) { | ||
const { left, width } = container.getBoundingClientRect(); | ||
const value = clamp(event.clientX - left, 0, width); | ||
const index = Math.round((value / width) * (max - min) + min); | ||
reset(index); | ||
} | ||
this.art.proxy(container, 'click', (event) => { | ||
updateLeft(event); | ||
}); | ||
onResize(); | ||
art.on('resize', () => { | ||
if (!art.isInput) { | ||
onResize(); | ||
this.art.proxy(container, 'mousedown', (event) => { | ||
isDroging = event.button === 0; | ||
}); | ||
this.art.on('document:mousemove', (event) => { | ||
if (isDroging) { | ||
updateLeft(event); | ||
} | ||
}); | ||
art.on('destroy', () => { | ||
if (option.mount && $emitter.parentElement === option.mount) { | ||
option.mount.removeChild($emitter); | ||
this.art.on('document:mouseup', (event) => { | ||
if (isDroging) { | ||
isDroging = false; | ||
updateLeft(event); | ||
} | ||
}); | ||
return { reset }; | ||
} | ||
function addControl() { | ||
art.controls.add({ | ||
position: 'right', | ||
name: 'danmuku', | ||
click: function () { | ||
if (danmuku.isHide) { | ||
danmuku.show(); | ||
art.notice.show = '弹幕显示'; | ||
setStyle($danmuOn, 'display', null); | ||
setStyle($danmuOff, 'display', 'none'); | ||
onFullscreen(state) { | ||
if (this.outside) { | ||
const { $danmuku, $controlsCenter, $mount } = this.template; | ||
if (state) { | ||
$controlsCenter.appendChild($danmuku); | ||
} else { | ||
$mount.appendChild($danmuku); | ||
} | ||
} | ||
} | ||
async emit() { | ||
const { $input } = this.template; | ||
const text = $input.value.trim(); | ||
if (!text.length) return; | ||
if (this.isLock) return; | ||
if (this.emitting) return; | ||
const danmu = { | ||
text: text, | ||
mode: this.option.mode, | ||
color: this.option.color, | ||
time: this.art.currentTime, | ||
}; | ||
try { | ||
this.emitting = true; | ||
const state = await this.option.beforeEmit(danmu); | ||
this.emitting = false; | ||
if (state !== true) return; | ||
danmu.border = true; | ||
delete danmu.time; | ||
this.danmuku.emit(danmu); | ||
$input.value = ''; | ||
this.lock(); | ||
// eslint-disable-next-line no-unused-vars | ||
} catch (error) { | ||
this.emitting = false; | ||
} | ||
} | ||
lock() { | ||
const { addClass } = this.utils; | ||
const { $send } = this.template; | ||
this.isLock = true; | ||
let time = this.option.lockTime; | ||
$send.innerText = time; | ||
addClass($send, 'apd-lock'); | ||
const loop = () => { | ||
this.timer = setTimeout(() => { | ||
if (time === 0) { | ||
this.unlock(); | ||
} else { | ||
danmuku.hide(); | ||
art.notice.show = '弹幕隐藏'; | ||
setStyle($danmuOn, 'display', 'none'); | ||
setStyle($danmuOff, 'display', null); | ||
time -= 1; | ||
$send.innerText = time; | ||
loop(); | ||
} | ||
}, | ||
mounted($ref) { | ||
append($ref, $danmuOn); | ||
append($ref, $danmuOff); | ||
tooltip($ref, '弹幕开关'); | ||
setStyle($danmuOff, 'display', 'none'); | ||
}, 1000); | ||
}; | ||
art.on('artplayerPluginDanmuku:hide', () => { | ||
setStyle($danmuOn, 'display', 'none'); | ||
setStyle($danmuOff, 'display', null); | ||
}); | ||
loop(); | ||
} | ||
art.on('artplayerPluginDanmuku:show', () => { | ||
setStyle($danmuOn, 'display', null); | ||
setStyle($danmuOff, 'display', 'none'); | ||
}); | ||
}, | ||
}); | ||
unlock() { | ||
const { removeClass } = this.utils; | ||
const { $send } = this.template; | ||
clearTimeout(this.timer); | ||
this.isLock = false; | ||
$send.innerText = '发送'; | ||
removeClass($send, 'apd-lock'); | ||
} | ||
function addSetting() { | ||
art.setting.add({ | ||
width: 260, | ||
name: 'danmuku', | ||
html: '弹幕设置', | ||
tooltip: '更多', | ||
icon: $danmuConfig, | ||
selector: [ | ||
{ | ||
width: SETTING_ITEM_WIDTH, | ||
html: '播放速度', | ||
icon: '', | ||
tooltip: '适中', | ||
selector: [ | ||
{ | ||
html: '极慢', | ||
time: 10, | ||
}, | ||
{ | ||
html: '较慢', | ||
time: 7.5, | ||
}, | ||
{ | ||
default: true, | ||
html: '适中', | ||
time: 5, | ||
}, | ||
{ | ||
html: '较快', | ||
time: 2.5, | ||
}, | ||
{ | ||
html: '极快', | ||
time: 1, | ||
}, | ||
], | ||
onSelect: function (item) { | ||
danmuku.config({ | ||
speed: item.time, | ||
}); | ||
return item.html; | ||
}, | ||
}, | ||
{ | ||
width: SETTING_ITEM_WIDTH, | ||
html: '字体大小', | ||
icon: '', | ||
tooltip: '适中', | ||
selector: [ | ||
{ | ||
html: '极小', | ||
fontSize: '4%', | ||
}, | ||
{ | ||
html: '较小', | ||
fontSize: '5%', | ||
}, | ||
{ | ||
default: true, | ||
html: '适中', | ||
fontSize: '6%', | ||
}, | ||
{ | ||
html: '较大', | ||
fontSize: '7%', | ||
}, | ||
{ | ||
html: '极大', | ||
fontSize: '8%', | ||
}, | ||
], | ||
onSelect: function (item) { | ||
danmuku.config({ | ||
fontSize: item.fontSize, | ||
}); | ||
return item.html; | ||
}, | ||
}, | ||
{ | ||
width: SETTING_ITEM_WIDTH, | ||
html: '不透明度', | ||
icon: '', | ||
tooltip: '100%', | ||
selector: [ | ||
{ | ||
default: true, | ||
opacity: 1, | ||
html: '100%', | ||
}, | ||
{ | ||
opacity: 0.75, | ||
html: '75%', | ||
}, | ||
{ | ||
opacity: 0.5, | ||
html: '50%', | ||
}, | ||
{ | ||
opacity: 0.25, | ||
html: '25%', | ||
}, | ||
{ | ||
opacity: 0, | ||
html: '0%', | ||
}, | ||
], | ||
onSelect: function (item) { | ||
danmuku.config({ | ||
opacity: item.opacity, | ||
}); | ||
return item.html; | ||
}, | ||
}, | ||
{ | ||
width: SETTING_ITEM_WIDTH, | ||
html: '显示范围', | ||
icon: '', | ||
tooltip: '3/4', | ||
selector: [ | ||
{ | ||
html: '1/4', | ||
margin: [10, '75%'], | ||
}, | ||
{ | ||
html: '半屏', | ||
margin: [10, '50%'], | ||
}, | ||
{ | ||
default: true, | ||
html: '3/4', | ||
margin: [10, '25%'], | ||
}, | ||
{ | ||
html: '满屏', | ||
margin: [10, 10], | ||
}, | ||
], | ||
onSelect: function (item) { | ||
danmuku.config({ | ||
margin: item.margin, | ||
}); | ||
return item.html; | ||
}, | ||
}, | ||
{ | ||
html: '弹幕防重叠', | ||
icon: '', | ||
tooltip: option.antiOverlap ? '开启' : '关闭', | ||
switch: option.antiOverlap, | ||
onSwitch(item) { | ||
danmuku.config({ | ||
antiOverlap: !item.switch, | ||
}); | ||
item.tooltip = item.switch ? '关闭' : '开启'; | ||
return !item.switch; | ||
}, | ||
}, | ||
{ | ||
html: '同步视频速度', | ||
icon: '', | ||
tooltip: option.synchronousPlayback ? '开启' : '关闭', | ||
switch: option.synchronousPlayback, | ||
onSwitch(item) { | ||
danmuku.config({ | ||
synchronousPlayback: !item.switch, | ||
}); | ||
item.tooltip = item.switch ? '关闭' : '开启'; | ||
return !item.switch; | ||
}, | ||
}, | ||
], | ||
}); | ||
reset() { | ||
const { inverseClass, tooltip } = this.utils; | ||
const { $toggle, $colors } = this.template; | ||
this.slider.opacity.reset(); | ||
this.slider.margin.reset(); | ||
this.slider.fontSize.reset(); | ||
this.slider.speed.reset(); | ||
this.setData('danmukuVisible', this.option.visible); | ||
this.setData('danmukuMode', this.option.mode); | ||
this.setData('danmukuColor', this.option.color); | ||
this.setData('danmukuMode0', this.option.modes.includes(0)); | ||
this.setData('danmukuMode1', this.option.modes.includes(1)); | ||
this.setData('danmukuMode2', this.option.modes.includes(2)); | ||
this.setData('danmukuAntiOverlap', this.option.antiOverlap); | ||
this.setData('danmukuSyncVideo', this.option.synchronousPlayback); | ||
this.setData('danmukuTheme', this.option.theme); | ||
this.setData('danmukuEmitter', this.option.emitter); | ||
const colors = $colors.children; | ||
const $color = Array.from(colors).find((item) => item.dataset.color === this.option.color.toUpperCase()); | ||
$color && inverseClass($color, 'apd-active'); | ||
tooltip($toggle, this.option.visible ? '关闭弹幕' : '打开弹幕'); | ||
} | ||
addEmitter(); | ||
addControl(); | ||
addSetting(); | ||
mount(target) { | ||
const $el = typeof target === 'string' ? document.querySelector(target) : target; | ||
$el.appendChild(this.template.$danmuku); | ||
this.template.$mount = $el; | ||
this.reset(); | ||
} | ||
} | ||
if (typeof document !== 'undefined') { | ||
if (!document.getElementById('artplayer-plugin-danmuku')) { | ||
const id = 'artplayer-plugin-danmuku'; | ||
const $style = document.getElementById(id); | ||
if ($style) { | ||
$style.textContent = style; | ||
} else { | ||
const $style = document.createElement('style'); | ||
$style.id = 'artplayer-plugin-danmuku'; | ||
$style.id = id; | ||
$style.textContent = style; | ||
@@ -400,0 +657,0 @@ document.head.appendChild($style); |
@@ -1,11 +0,22 @@ | ||
function getDanmuTop({ target, emits, clientWidth, clientHeight, marginBottom, marginTop, antiOverlap }) { | ||
const danmus = emits | ||
.filter((item) => item.mode === target.mode && item.top <= clientHeight - marginBottom) | ||
function getDanmuTop({ target, visibles, clientWidth, clientHeight, marginBottom, marginTop, antiOverlap }) { | ||
// 弹幕最大高度 | ||
const maxTop = clientHeight - marginBottom; | ||
// 过滤同模式的弹幕,即每种模式各不影响 | ||
const danmus = visibles | ||
.filter((item) => item.mode === target.mode && item.top <= maxTop) | ||
.sort((prev, next) => prev.top - next.top); | ||
// 如果没有同模式的弹幕,直接返回 | ||
if (danmus.length === 0) { | ||
return marginTop; | ||
if (target.mode === 2) { | ||
return maxTop - target.height; | ||
} else { | ||
return marginTop; | ||
} | ||
} | ||
// 上下各加一个虚拟弹幕,方便计算 | ||
danmus.unshift({ | ||
type: 'top', | ||
top: 0, | ||
@@ -21,3 +32,4 @@ left: 0, | ||
danmus.push({ | ||
top: clientHeight - marginBottom, | ||
type: 'bottom', | ||
top: maxTop, | ||
left: 0, | ||
@@ -31,10 +43,25 @@ right: 0, | ||
for (let index = 1; index < danmus.length; index += 1) { | ||
const item = danmus[index]; | ||
const prev = danmus[index - 1]; | ||
const prevBottom = prev.top + prev.height; | ||
const diff = item.top - prevBottom; | ||
if (diff >= target.height) { | ||
return prevBottom; | ||
// 查找是否有多余的缝隙足以容纳当前弹幕 | ||
if (target.mode === 2) { | ||
// 倒序查找 | ||
for (let index = danmus.length - 2; index >= 0; index -= 1) { | ||
const item = danmus[index]; | ||
const prev = danmus[index + 1]; | ||
const itemBottom = item.top + item.height; | ||
const diff = prev.top - itemBottom; | ||
if (diff >= target.height) { | ||
return prev.top - target.height; | ||
} | ||
} | ||
} else { | ||
// 顺序查找 | ||
for (let index = 1; index < danmus.length; index += 1) { | ||
const item = danmus[index]; | ||
const prev = danmus[index - 1]; | ||
const prevBottom = prev.top + prev.height; | ||
const diff = item.top - prevBottom; | ||
if (diff >= target.height) { | ||
return prevBottom; | ||
} | ||
} | ||
} | ||
@@ -72,3 +99,6 @@ | ||
} | ||
// 静止弹幕没有重叠问题 | ||
case 1: | ||
case 2: | ||
return undefined; | ||
@@ -88,2 +118,3 @@ default: | ||
case 1: | ||
case 2: | ||
topMap.sort((prev, next) => { | ||
@@ -105,2 +136,3 @@ const nextMaxWidth = Math.max(...next.map((item) => item.width)); | ||
const { data } = event; | ||
if (!data.id) return; | ||
const top = getDanmuTop(data); | ||
@@ -107,0 +139,0 @@ self.postMessage({ |
@@ -6,2 +6,14 @@ import type Artplayer from 'artplayer'; | ||
type Mode = 0 | 1 | 2; | ||
type Slider = { | ||
min: number; | ||
max: number; | ||
steps: { | ||
name?: string; | ||
value?: any; | ||
show?: boolean; | ||
}[]; | ||
}; | ||
type Danmu = { | ||
@@ -14,5 +26,5 @@ /** | ||
/** | ||
* 弹幕发送模式,0为滚动,1为静止 | ||
* 弹幕发送模式: 0: 滚动,1: 顶部,2: 底部 | ||
*/ | ||
mode?: 0 | 1; | ||
mode?: Mode; | ||
@@ -30,5 +42,10 @@ /** | ||
/** | ||
* 弹幕是否有描边 | ||
* 弹幕是否有描边, 默认为 false | ||
*/ | ||
border?: boolean; | ||
/** | ||
* 弹幕自定义样式 | ||
*/ | ||
style?: Partial<CSSStyleDeclaration>; | ||
}; | ||
@@ -38,3 +55,3 @@ | ||
/** | ||
* 弹幕源,可以是弹幕数组,xml 地址或者一个返回 Promise 的函数 | ||
* 弹幕数据: 函数,数组,Promise,URL | ||
*/ | ||
@@ -44,3 +61,3 @@ danmuku: Danmu[] | string | (() => Promise<Danmu[]>) | Promise<Danmu[]>; | ||
/** | ||
* 弹幕持续时间,单位秒,范围在[1 ~ 10] | ||
* 弹幕持续时间,范围在[1 ~ 10] | ||
*/ | ||
@@ -50,3 +67,3 @@ speed?: number; | ||
/** | ||
* 弹幕上下边距,支持数字和高度的百分比 | ||
* 弹幕上下边距,支持像素数字和百分比 | ||
*/ | ||
@@ -61,3 +78,3 @@ margin?: [number | `${number}%`, number | `${number}%`]; | ||
/** | ||
* 默认字体颜色 | ||
* 默认弹幕颜色,可以被单独弹幕项覆盖 | ||
*/ | ||
@@ -67,38 +84,81 @@ color?: string; | ||
/** | ||
* 默认弹幕发送模式,0为滚动,1为静止 | ||
* 弹幕模式: 0: 滚动,1: 顶部,2: 底部 | ||
*/ | ||
mode?: 0 | 1; | ||
mode?: Mode; | ||
/** | ||
* 字体大小,支持数字和高度的百分比 | ||
* 弹幕可见的模式 | ||
*/ | ||
modes?: Mode[]; | ||
/** | ||
* 弹幕字体大小,支持像素数字和百分比 | ||
*/ | ||
fontSize?: number | `${number}%`; | ||
/** | ||
* 弹幕过滤函数,返回 true 则可以发送 | ||
* 弹幕是否防重叠 | ||
*/ | ||
antiOverlap?: boolean; | ||
/** | ||
* 是否同步播放速度 | ||
*/ | ||
synchronousPlayback?: boolean; | ||
/** | ||
* 弹幕发射器挂载点, 默认为播放器控制栏中部 | ||
*/ | ||
mount?: HTMLDivElement | string; | ||
/** | ||
* 是否开启弹幕热度图 | ||
*/ | ||
heatmap?: | ||
| boolean | ||
| { | ||
xMin?: number; | ||
xMax?: number; | ||
yMin?: number; | ||
yMax?: number; | ||
scale?: number; | ||
opacity?: number; | ||
minHeight?: number; | ||
sampling?: number; | ||
smoothing?: number; | ||
flattening?: number; | ||
}; | ||
/** | ||
* 热力图数据 | ||
*/ | ||
points?: any[]; | ||
/** | ||
* 弹幕载入前的过滤器,只支持返回布尔值 | ||
*/ | ||
filter?: (danmu: Danmu) => boolean; | ||
/** | ||
* 是否防重叠 | ||
* 弹幕发送前的过滤器,支持返回 Promise | ||
*/ | ||
antiOverlap?: boolean; | ||
beforeEmit?: (danmu: Danmu) => boolean | Promise<boolean>; | ||
/** | ||
* 是否使用 web worker | ||
* 弹幕显示前的过滤器,支持返回 Promise | ||
*/ | ||
useWorker?: boolean; | ||
beforeVisible?: (danmu: Danmu) => boolean | Promise<boolean>; | ||
/** | ||
* 是否同步到播放速度 | ||
* 弹幕是否可见 | ||
*/ | ||
synchronousPlayback?: boolean; | ||
visible?: boolean; | ||
/** | ||
* 输入框锁定时间,单位秒,范围在[1 ~ 60] | ||
* 是否开启弹幕发射器 | ||
*/ | ||
lockTime?: number; | ||
emitter?: boolean; | ||
/** | ||
* 输入框最大可输入的字数,范围在[0 ~ 500] | ||
* 弹幕输入框最大长度, 范围在[1 ~ 1000] | ||
*/ | ||
@@ -108,43 +168,35 @@ maxLength?: number; | ||
/** | ||
* 输入框最小宽度,范围在[0 ~ 500],填 0 则为无限制 | ||
* 输入框锁定时间,范围在[1 ~ 60] | ||
*/ | ||
minWidth?: number; | ||
lockTime?: number; | ||
/** | ||
* 输入框最大宽度,范围在[0 ~ Infinity],填 0 则为 100% 宽度 | ||
* 弹幕主题,只在自定义挂载时生效 | ||
*/ | ||
maxWidth?: number; | ||
theme?: 'light' | 'dark'; | ||
/** | ||
* 通过 mount 选项可以自定义输入框挂载的位置,默认挂载于播放器底部,仅在当宽度小于最小值时生效 | ||
* 不透明度配置项 | ||
*/ | ||
mount?: Element; | ||
OPACITY?: Slider; | ||
/** | ||
* 输入框自定义挂载时的主题色,默认为 dark,可以选填亮色 light | ||
* 弹幕速度配置项 | ||
*/ | ||
theme?: 'dark' | 'light'; | ||
SPEED?: Slider; | ||
/** | ||
* 是否开启弹幕热度图 | ||
* 显示区域配置项 | ||
*/ | ||
heatmap?: | ||
| boolean | ||
| { | ||
xMin?: number; | ||
xMax?: number; | ||
yMin?: number; | ||
yMax?: number; | ||
scale?: number; | ||
opacity?: number; | ||
minHeight?: number; | ||
sampling?: number; | ||
smoothing?: number; | ||
flattening?: number; | ||
}; | ||
MARGIN?: Slider; | ||
/** | ||
* 发送弹幕前的自定义校验,返回 true 则可以发送 | ||
* 弹幕字号配置项 | ||
*/ | ||
beforeEmit?: (danmu: Danmu) => boolean; | ||
FONT_SIZE?: Slider; | ||
/** | ||
* 颜色列表配置项 | ||
*/ | ||
COLOR?: string[]; | ||
}; | ||
@@ -181,2 +233,17 @@ | ||
/** | ||
* 挂载弹幕输入框 | ||
*/ | ||
mount: (el?: HTMLDivElement | string) => void; | ||
/** | ||
* 重置弹幕 | ||
*/ | ||
reset: () => Danmuku; | ||
/** | ||
* 弹幕配置 | ||
*/ | ||
option: Option; | ||
/** | ||
* 是否隐藏弹幕层 | ||
@@ -183,0 +250,0 @@ */ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
215239
24
1771
0
1
12
4