@applemusic-like-lyrics/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/dist/amll-core.js +1 -0
- package/dist/amll-core.mjs +904 -0
- package/dist/bg-render/index.d.ts +13 -0
- package/dist/bg-render/pixi-renderer.d.ts +19 -0
- package/dist/index.d.ts +2 -0
- package/dist/interfaces.d.ts +51 -0
- package/dist/lyric/ttml.d.ts +2 -0
- package/dist/lyric-player/index.d.ts +87 -0
- package/dist/lyric-player/interlude-dots.d.ts +22 -0
- package/dist/lyric-player/lyric-line.d.ts +40 -0
- package/dist/utils/eq-set.d.ts +1 -0
- package/dist/utils/spring.d.ts +25 -0
- package/package.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var w=Object.defineProperty;var v=(d,t,e)=>t in d?w(d,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):d[t]=e;var l=(d,t,e)=>(v(d,typeof t!="symbol"?t+"":t,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const x=require("@pixi/display"),C=require("@pixi/app"),f=require("@pixi/filter-blur"),b=require("@pixi/filter-color-matrix"),M=require("@pixi/core"),L=require("@pixi/sprite"),z=require("jss"),B=require("jss-preset-default");class I extends x.Container{constructor(){super(...arguments);l(this,"time",0)}}class A{constructor(t){l(this,"observer");l(this,"app");l(this,"curContainer");l(this,"lastContainer",new Set);l(this,"onTick",t=>{for(const e of this.lastContainer)e.alpha=Math.max(0,e.alpha-t/60),e.alpha<=0&&(this.app.stage.removeChild(e),this.lastContainer.delete(e));if(this.curContainer){this.curContainer.alpha=Math.min(1,this.curContainer.alpha+t/60);const[e,r,s,a]=this.curContainer.children,h=Math.max(this.app.screen.width,this.app.screen.height);e.position.set(this.app.screen.width/2,this.app.screen.height/2),r.position.set(this.app.screen.width/2.5,this.app.screen.height/2.5),s.position.set(this.app.screen.width/2,this.app.screen.height/2),a.position.set(this.app.screen.width/2,this.app.screen.height/2),e.width=h*Math.sqrt(2),e.height=e.width,r.width=h*.8,r.height=r.width,s.width=h*.5,s.height=s.width,a.width=h*.25,a.height=a.width,this.curContainer.time+=t*this.flowSpeed,e.rotation+=t/1e3*this.flowSpeed,r.rotation-=t/500*this.flowSpeed,s.rotation+=t/1e3*this.flowSpeed,a.rotation-=t/750*this.flowSpeed,s.x=this.app.screen.width/2+this.app.screen.width/4*Math.cos(this.curContainer.time/1e3*.75),s.y=this.app.screen.height/2+this.app.screen.width/4*Math.cos(this.curContainer.time/1e3*.75),a.x=this.app.screen.width/2+this.app.screen.width/4*.1+Math.cos(this.curContainer.time*.006*.75),a.y=this.app.screen.height/2+this.app.screen.width/4*.1+Math.cos(this.curContainer.time*.006*.75)}});l(this,"flowSpeed",2);l(this,"currerntRenderScale",.75);this.canvas=t;const e=t.getBoundingClientRect();this.canvas.width=e.width*this.currerntRenderScale,this.canvas.height=e.height*this.currerntRenderScale,this.observer=new ResizeObserver(()=>{const r=t.getBoundingClientRect();this.canvas.width=Math.max(1,r.width),this.canvas.height=Math.max(1,r.height),this.app.renderer.resize(this.canvas.width*this.currerntRenderScale,this.canvas.height*this.currerntRenderScale),this.rebuildFilters()}),this.observer.observe(t),this.app=new C.Application({view:t,resizeTo:this.canvas,powerPreference:"low-power",backgroundAlpha:0}),this.rebuildFilters(),this.app.ticker.add(this.onTick),this.app.ticker.start()}setRenderScale(t){this.currerntRenderScale=t;const e=this.canvas.getBoundingClientRect();this.canvas.width=Math.max(1,e.width),this.canvas.height=Math.max(1,e.height),this.app.renderer.resize(this.canvas.width*this.currerntRenderScale,this.canvas.height*this.currerntRenderScale),this.rebuildFilters()}rebuildFilters(){const t=Math.min(this.canvas.width,this.canvas.height),e=new b.ColorMatrixFilter;e.saturate(1.2,!1);const r=new b.ColorMatrixFilter;r.brightness(.6,!1);const s=new b.ColorMatrixFilter;s.contrast(.3,!0),this.app.stage.filters=[],this.app.stage.filters.push(new f.BlurFilter(5,1)),this.app.stage.filters.push(new f.BlurFilter(10,1)),this.app.stage.filters.push(new f.BlurFilter(20,2)),this.app.stage.filters.push(new f.BlurFilter(40,2)),t>512&&this.app.stage.filters.push(new f.BlurFilter(80,2)),t>768&&this.app.stage.filters.push(new f.BlurFilter(160,4)),t>768*2&&this.app.stage.filters.push(new f.BlurFilter(320,4)),this.app.stage.filters.push(e,r,s),this.app.stage.filters.push(new f.BlurFilter(5,1))}setFPS(t){this.app.ticker.maxFPS=t}pause(){this.app.ticker.stop(),this.app.render()}resume(){this.app.ticker.start()}async setAlbumImage(t){const e=await M.Texture.fromURL(t),r=new I,s=new L.Sprite(e),a=new L.Sprite(e),h=new L.Sprite(e),i=new L.Sprite(e);s.anchor.set(.5,.5),a.anchor.set(.5,.5),h.anchor.set(.5,.5),i.anchor.set(.5,.5),s.rotation=Math.random()*Math.PI*2,a.rotation=Math.random()*Math.PI*2,h.rotation=Math.random()*Math.PI*2,i.rotation=Math.random()*Math.PI*2,r.addChild(s,a,h,i),this.curContainer&&this.lastContainer.add(this.curContainer),this.curContainer=r,this.app.stage.addChild(this.curContainer),this.curContainer.alpha=0}dispose(){this.observer.disconnect(),this.app.ticker.remove(this.onTick)}}class D extends A{constructor(){const e=document.createElement("canvas");super(e);l(this,"element");this.element=e,e.style.pointerEvents="none",e.style.zIndex="-1"}getElement(){return this.element}dispose(){super.dispose(),this.element.remove()}}const k=(d,t)=>d.size===t.size&&[...d].every(e=>t.has(e));function q(d){const e=2.5949095;return d<.5?Math.pow(2*d,2)*((e+1)*2*d-e)/2:(Math.pow(2*d-2,2)*((e+1)*(d*2-2)+e)+2)/2}const y=(d,t,e)=>Math.max(d,Math.min(t,e));class F{constructor(t){l(this,"element",document.createElement("div"));l(this,"dot0",document.createElement("span"));l(this,"dot1",document.createElement("span"));l(this,"dot2",document.createElement("span"));l(this,"left",0);l(this,"top",0);l(this,"scale",1);l(this,"lastStyle","");l(this,"currentInterlude");l(this,"currentTime",0);l(this,"targetBreatheDuration",1500);this.lyricPlayer=t,this.element.className=this.lyricPlayer.style.classes.interludeDots,this.element.appendChild(this.dot0),this.element.appendChild(this.dot1),this.element.appendChild(this.dot2)}getElement(){return this.element}setTransform(t=this.left,e=this.top){this.left=t,this.top=e,this.update()}setInterlude(t){this.currentInterlude=t,this.currentTime=(t==null?void 0:t[0])??0}update(t=0){this.currentTime+=t;let e="";if(e+=`transform:translate(${this.left}px, ${this.top}px)`,this.currentInterlude){const r=this.currentInterlude[1]-this.currentInterlude[0],s=this.currentTime-this.currentInterlude[0];if(s<=r){const a=r/Math.ceil(r/this.targetBreatheDuration);let h=1,i=1;h*=Math.sin(1.5*Math.PI-s/a*2)/10+1,s<1e3&&(h*=1-Math.pow((1e3-s)/1e3,2)),s<500?i=0:s<1e3&&(i*=(s-500)/500),r-s<750&&(h*=1-q((750-(r-s))/750/2)),r-s<375&&(i*=y(0,(r-s)/375,1)),h=Math.max(0,h),e+=` scale(${h})`;const n=y(.25,s*3/r*.75,1),c=y(.25,(s-r/3)*3/r*.75,1),o=y(.25,(s-r/3*2)*3/r*.75,1);this.dot0.style.opacity=`${y(0,Math.max(0,i*n),1)}`,this.dot1.style.opacity=`${y(0,Math.max(0,i*c),1)}`,this.dot2.style.opacity=`${y(0,Math.max(0,i*o),1)}`}else e+=" scale(0)",this.dot0.style.opacity="0",this.dot1.style.opacity="0",this.dot2.style.opacity="0"}else e+=" scale(0)",this.dot0.style.opacity="0",this.dot1.style.opacity="0",this.dot2.style.opacity="0";e+=";",this.lastStyle!==e&&(this.element.setAttribute("style",e),this.lastStyle=e)}dispose(){this.element.remove()}}class S{constructor(t=0){l(this,"currentPosition",0);l(this,"targetPosition",0);l(this,"currentTime",0);l(this,"params",{});l(this,"currentSolver");l(this,"getV");l(this,"queueParams");l(this,"queuePosition");this.targetPosition=t,this.currentPosition=this.targetPosition,this.currentSolver=()=>this.targetPosition,this.getV=()=>0}resetSolver(){const t=this.getV(this.currentTime);this.currentTime=0,this.currentSolver=$(this.currentPosition,t,this.targetPosition,0,this.params),this.getV=O(this.currentSolver)}arrived(){return Math.abs(this.targetPosition-this.currentPosition)<.01&&this.getV(this.currentTime)<.01&&this.queueParams===void 0&&this.queuePosition===void 0}setPosition(t){this.targetPosition=t,this.currentPosition=t,this.currentSolver=()=>this.targetPosition,this.getV=()=>0}update(t=0){this.currentTime+=t,this.currentPosition=this.currentSolver(this.currentTime),this.queueParams&&(this.queueParams.time-=t,this.queueParams.time<=0&&this.updateParams({...this.queueParams})),this.queuePosition&&(this.queuePosition.time-=t,this.queuePosition.time<=0&&this.setTargetPosition(this.queuePosition.position)),this.arrived()&&this.setPosition(this.targetPosition)}updateParams(t,e=0){e>0?this.queueParams={...t,time:e}:(this.params={...this.params,...t},this.resetSolver())}setTargetPosition(t,e=0){e>0?this.queuePosition={position:t,time:e}:(this.queuePosition=void 0,this.targetPosition=t,this.resetSolver())}getCurrentPosition(){return this.currentPosition}}function $(d,t,e,r=0,s){const a=(s==null?void 0:s.soft)??!1,h=(s==null?void 0:s.stiffness)??100,i=(s==null?void 0:s.damping)??10,n=(s==null?void 0:s.mass)??1,c=e-d;if(a||1<=i/(2*Math.sqrt(h*n))){const o=-Math.sqrt(h/n),m=-o*c-t;return p=>(p-=r,p<0?d:e-(c+p*m)*Math.E**(p*o))}else{const o=Math.sqrt(4*n*h-i**2),m=(i*c-2*n*t)/o,p=.5*o/n,g=-(.5*i)/n;return u=>(u-=r,u<0?d:e-(Math.cos(u*p)*c+Math.sin(u*p)*m)*Math.E**(u*g))}}function R(d){return e=>(d(e+.001)-d(e-.001))/(2*.001)}function O(d){return R(d)}const T=/^[\p{Unified_Ideograph}\u0800-\u9FFC]+$/u;function W(d,t="rgba(0,0,0,1)",e="rgba(0,0,0,0.5)"){const r=2+d,s=d/r,a=(1-s)/2;return[`linear-gradient(to right,${t} ${a*100}%,${e} ${(a+s)*100}%)`,s,r]}function P(d){return d.endTime-d.startTime>=1e3&&d.word.length<=7}class G{constructor(t,e={words:[],translatedLyric:"",romanLyric:"",startTime:0,endTime:0,isBG:!1,isDuet:!1}){l(this,"element",document.createElement("div"));l(this,"left",0);l(this,"top",0);l(this,"scale",1);l(this,"blur",0);l(this,"delay",0);l(this,"splittedWords",[]);l(this,"lineSize",[0,0]);l(this,"lineTransforms",{posX:new S(0),posY:new S(0),scale:new S(1)});l(this,"_hide",!0);l(this,"lastStyle","");this.lyricPlayer=t,this.lyricLine=e,this.element.setAttribute("class",this.lyricPlayer.style.classes.lyricLine),this.lyricLine.isBG&&this.element.classList.add(this.lyricPlayer.style.classes.lyricBgLine),this.lyricLine.isDuet&&this.element.classList.add(this.lyricPlayer.style.classes.lyricDuetLine),this.element.appendChild(document.createElement("div")),this.element.appendChild(document.createElement("div")),this.element.appendChild(document.createElement("div"));const r=this.element.children[0],s=this.element.children[1],a=this.element.children[2];r.setAttribute("class",this.lyricPlayer.style.classes.lyricMainLine),s.setAttribute("class",this.lyricPlayer.style.classes.lyricSubLine),a.setAttribute("class",this.lyricPlayer.style.classes.lyricSubLine),this.rebuildElement(),this.rebuildStyle()}enable(){this.element.classList.add("active");const t=this.element.children[0];this.splittedWords.forEach(e=>{e.elementAnimations.forEach(r=>{r.currentTime=0,r.playbackRate=1,r.play()})}),t.classList.add("active")}disable(){this.element.classList.remove("active");const t=this.element.children[0];this.splittedWords.forEach(e=>{e.elementAnimations.forEach(r=>{r.id==="float-word"&&(r.playbackRate=-1,r.play())})}),t.classList.remove("active")}setLine(t){this.lyricLine=t,this.lyricLine.isBG?this.element.classList.add(this.lyricPlayer.style.classes.lyricBgLine):this.element.classList.remove(this.lyricPlayer.style.classes.lyricBgLine),this.lyricLine.isDuet?this.element.classList.add(this.lyricPlayer.style.classes.lyricDuetLine):this.element.classList.remove(this.lyricPlayer.style.classes.lyricDuetLine),this.rebuildElement(),this.rebuildStyle()}getLine(){return this.lyricLine}show(){this._hide=!1,this.rebuildStyle()}hide(){this._hide=!0,this.rebuildStyle()}rebuildStyle(){if(this._hide){this.lastStyle!=="visibility:hidden;transform:translate(0,-10000px);"&&(this.lastStyle="visibility:hidden;transform:translate(0,-10000px);",this.element.setAttribute("style","visibility:hidden;transform:translate(0,-10000px);"));return}let t=`transform:translate(${this.lineTransforms.posX.getCurrentPosition()}px,${this.lineTransforms.posY.getCurrentPosition()}px) scale(${this.lineTransforms.scale.getCurrentPosition()});`;this.lyricPlayer.disableSpring&&this.isInSight&&(t+=`transition-delay:${this.delay}ms;`),t+=`filter:blur(${Math.min(32,this.blur)}px);`,t!==this.lastStyle&&(this.lastStyle=t,this.element.setAttribute("style",t))}rebuildElement(){const t=this.element.children[0],e=this.element.children[1],r=this.element.children[2];this.splittedWords=[],this.lyricLine.words.forEach(n=>{if(T.test(n.word))this.splittedWords.push({...n,width:0,height:0,elements:[],elementAnimations:[],shouldEmphasize:P(n)});else{const c=/(\s*)(\S*)(\s*)/.exec(n.word);c&&(c[1].length>0&&this.splittedWords.push({word:" ",startTime:0,endTime:0,width:0,height:0,elements:[],elementAnimations:[],shouldEmphasize:!1}),this.splittedWords.push({word:c[2],startTime:n.startTime,endTime:n.endTime,width:0,height:0,elements:[],elementAnimations:[],shouldEmphasize:P(n)}),c[3].length>0&&this.splittedWords.push({word:" ",startTime:0,endTime:0,width:0,height:0,elements:[],elementAnimations:[],shouldEmphasize:!1}))}});const s=[],a=[];function h(n){for(;n.firstChild;)n.firstChild.nodeType===Node.ELEMENT_NODE?s.push(t.firstChild):n.firstChild.nodeType===Node.TEXT_NODE&&a.push(t.firstChild),n.removeChild(n.firstChild),h(n.firstChild)}h(t);let i=null;this.splittedWords.forEach(n=>{if(n.word.trim().length>0)if(n.shouldEmphasize){const c=s.pop()??document.createElement("span");c.className="emphasize",n.elements=[c];for(const o of n.word){const m=s.pop()??document.createElement("span");m.className="",m.innerText=o,c.appendChild(m),n.elements.push(m)}if(n.elementAnimations=this.initEmphasizeAnimation(n),console.log(n.word,T.test(n.word)),i&&!T.test(n.word))if(i.childElementCount>0)i.appendChild(c);else{const o=s.pop()??document.createElement("span");o.className="",i.remove(),o.appendChild(i),o.appendChild(c),t.appendChild(o),i=o}else i=T.test(n.word)?null:c,t.appendChild(c)}else{const c=s.pop()??document.createElement("span");if(c.className="",c.innerText=n.word,n.elements=[c],n.elementAnimations.push(this.initFloatAnimation(n,c)),i)if(i.childElementCount>0)i.appendChild(c);else{const o=s.pop()??document.createElement("span");o.className="",i.remove(),o.appendChild(i),o.appendChild(c),t.appendChild(o),i=o}else i=c,t.appendChild(c)}else if(n.word.length>0){const c=a.pop()??document.createTextNode(" ");t.appendChild(c),i=null}else i=null}),e.innerText=this.lyricLine.translatedLyric,r.innerText=this.lyricLine.romanLyric}initFloatAnimation(t,e){const r=e.animate([{transform:"translateY(0px)"},{transform:"translateY(-3%)"}],{duration:Math.max(1e3,t.endTime-t.startTime),delay:t.startTime-this.lyricLine.startTime,id:"float-word",composite:"add",fill:"both"});return r.pause(),r}initEmphasizeAnimation(t){const e=t.startTime-this.lyricLine.startTime,r=t.endTime-t.startTime;return t.elements.map((s,a,h)=>{if(a===0)return this.initFloatAnimation(t,s);{const i=s.animate([{offset:0,transform:"translate3d(0, 0px, 0px)",filter:"drop-shadow(0 0 0 var(--amll-lyric-line-color))"},{offset:.5,transform:"translate3d(0, -2%, 20px)",filter:"drop-shadow(0 0 0.2rem var(--amll-lyric-line-color))"},{offset:1,transform:"translate3d(0, 0px, 0)",filter:"drop-shadow(0 0 0 var(--amll-lyric-line-color))"}],{duration:Math.max(1e3,t.endTime-t.startTime),delay:e+r/(h.length-1)*(a-1),id:"glow-word",iterations:1,composite:"replace",fill:"both"});return i.pause(),i}})}updateMaskImage(){this.splittedWords.forEach(t=>{const e=t.elements[0];if(e){t.width=e.clientWidth,t.height=e.clientHeight;const[r,s,a]=W(16/t.width,"rgba(0,0,0,0.75)","rgba(0,0,0,0.25)"),h=`${a*100}% 100%`;this.lyricPlayer.supportMaskImage?(e.style.maskImage=r,e.style.maskOrigin="left",e.style.maskSize=h):(e.style.webkitMaskImage=r,e.style.webkitMaskOrigin="left",e.style.webkitMaskSize=h);const i=t.width+16,n=`clamp(${-i}px,calc(${-i}px + (var(--amll-player-time) - ${t.startTime})*${i/Math.abs(t.endTime-t.startTime)}px),0px) 0px, left top`;e.style.maskPosition=n,e.style.webkitMaskPosition=n}})}getElement(){return this.element}setTransform(t=this.left,e=this.top,r=this.scale,s=1,a=0,h=!1,i=0){this.left=t,this.top=e,this.scale=r,this.delay=i*1e3|0;const n=this.element.children[0];n.style.opacity=`${s}`,h||this.lyricPlayer.disableSpring?(this.blur=Math.min(32,a),h&&this.element.classList.add(this.lyricPlayer.style.classes.tmpDisableTransition),this.lineTransforms.posX.setPosition(t),this.lineTransforms.posY.setPosition(e),this.lineTransforms.scale.setPosition(r),this.lyricPlayer.disableSpring?this.show():this.rebuildStyle(),h&&requestAnimationFrame(()=>{this.element.classList.remove(this.lyricPlayer.style.classes.tmpDisableTransition)})):(this.lineTransforms.posX.setTargetPosition(t,i),this.lineTransforms.posY.setTargetPosition(e,i),this.lineTransforms.scale.setTargetPosition(r),this.blur!==Math.min(32,a)&&(this.blur=Math.min(32,a),this.element.style.filter=`blur(${Math.min(32,a)}px)`))}update(t=0){this.lyricPlayer.disableSpring||(this.lineTransforms.posX.update(t),this.lineTransforms.posY.update(t),this.lineTransforms.scale.update(t),this.isInSight?this.show():this.hide())}get isInSight(){const t=this.lineTransforms.posX.getCurrentPosition(),e=this.lineTransforms.posY.getCurrentPosition(),r=t+this.lineSize[0],s=e+this.lineSize[1],a=this.lyricPlayer.pos[0],h=this.lyricPlayer.pos[1],i=this.lyricPlayer.pos[0]+this.lyricPlayer.size[0],n=this.lyricPlayer.pos[1]+this.lyricPlayer.size[1];return!(t>i||e>n||r<a||s<h)}dispose(){this.element.remove()}}const X=z.create(B());class Y extends EventTarget{constructor(){super();l(this,"element",document.createElement("div"));l(this,"currentTime",0);l(this,"lyricLines",[]);l(this,"processedLines",[]);l(this,"lyricLinesEl",[]);l(this,"lyricLinesSize",new Map);l(this,"hotLines",new Set);l(this,"bufferedLines",new Set);l(this,"scrollToIndex",0);l(this,"resizeObserver",new ResizeObserver(e=>{const r=e[0].contentRect;this.size[0]=r.width,this.size[1]=r.height,this.pos[0]=r.left,this.pos[1]=r.top,this.rebuildStyle(),this.calcLayout(!0),this.lyricLinesEl.forEach(s=>s.updateMaskImage())}));l(this,"posXSpringParams",{mass:1,damping:10,stiffness:100});l(this,"posYSpringParams",{mass:1,damping:15,stiffness:100});l(this,"scaleSpringParams",{mass:1,damping:20,stiffness:100});l(this,"enableBlur",!0);l(this,"interludeDots");l(this,"interludeDotsSize",[0,0]);l(this,"supportPlusLighter",CSS.supports("mix-blend-mode","plus-lighter"));l(this,"supportMaskImage",CSS.supports("mask-image","none"));l(this,"disableSpring",!1);l(this,"alignAnchor",.5);l(this,"size",[0,0]);l(this,"pos",[0,0]);l(this,"style",X.createStyleSheet({lyricPlayer:{userSelect:"none",padding:"1rem",boxSizing:"border-box",fontSize:"max(5vh, 12px)",fontWeight:"bold",width:"100%",height:"100%",overflow:"hidden",maxWidth:"100%",maxHeight:"100%",zIndex:1,color:"var(--amll-lyric-line-color)",mixBlendMode:"plus-lighter",contain:"strict"},lyricLine:{position:"absolute",transformOrigin:"left",maxWidth:"65%",padding:"max(2vh, 1rem) 1rem",contain:"content",transition:"filter 0.25s",margin:"max(2vh, 1rem) -1rem"},"@media (max-width: 1024px)":{lyricLine:{maxWidth:"75%",padding:"max(1vh, 1rem) 1rem",margin:"0 -1rem"}},lyricDuetLine:{textAlign:"right",transformOrigin:"right"},lyricBgLine:{opacity:0,fontSize:"max(50%, 10px)",transition:"opacity 0.25s","&.active":{transition:"opacity 0.25s 0.25s",opacity:1}},lyricMainLine:{transition:"opacity 0.3s 0.25s",margin:"-1rem",padding:"1rem","& span":{display:"inline-block",margin:"-1rem",padding:"1rem"},"& > span":{whiteSpace:"pre-wrap",wordBreak:"keep-all",maxLines:"1","&.emphasize":{margin:"-1rem",padding:"1rem",transformStyle:"preserve-3d",perspective:"50vw"}}},lyricSubLine:{fontSize:"max(50%, 10px)",opacity:.5},disableSpring:{"& > *":{transition:"filter 0.25s, transform 0.5s"}},interludeDots:{height:"min(1rem,2.5vh)",transformOrigin:"center",width:"fit-content",padding:"2.5% 0",position:"absolute",display:"flex",gap:"0.5rem","& > *":{width:"100%",display:"inline-block",borderRadius:"50%",aspectRatio:"1 / 1",backgroundColor:"var(--amll-lyric-line-color)",marginRight:"4px"},"&.duet":{right:"1rem",transformOrigin:"center"}},"@supports (mix-blend-mode: plus-lighter)":{lyricSubLine:{opacity:.3}},tmpDisableTransition:{transition:"none !important"}}));l(this,"onPageShow",()=>{this.calcLayout(!0)});this.interludeDots=new F(this),this.element.setAttribute("class",this.style.classes.lyricPlayer),this.disableSpring&&this.element.classList.add(this.style.classes.disableSpring),this.rebuildStyle(),this.resizeObserver.observe(this.element),this.element.appendChild(this.interludeDots.getElement()),this.style.attach(),this.interludeDots.setTransform(0,200),window.addEventListener("pageshow",this.onPageShow)}setEnableSpring(e=!0){this.disableSpring=!e,e?this.element.classList.remove(this.style.classes.disableSpring):this.element.classList.add(this.style.classes.disableSpring),this.calcLayout(!0)}getCurrentInterlude(){var s,a,h;if(this.bufferedLines.size>0)return;const e=this.currentTime+20,r=this.scrollToIndex;if(r===0){if((s=this.processedLines[0])!=null&&s.startTime&&this.processedLines[0].startTime>e)return[0,this.processedLines[0].startTime]}else if((a=this.processedLines[r])!=null&&a.endTime&&((h=this.processedLines[r+1])!=null&&h.startTime)&&this.processedLines[r+1].startTime>e&&this.processedLines[r].endTime<e)return[this.processedLines[r].endTime,this.processedLines[r+1].startTime]}rebuildStyle(){let e="";e+="--amll-lyric-player-width:",e+=this.element.clientWidth,e+="px;",e+="--amll-lyric-player-height:",e+=this.element.clientHeight,e+="px;",e+="--amll-lyric-line-color:",e+="#FFFFFF;",e+="--amll-player-time:",e+=this.currentTime,e+=";",this.element.setAttribute("style",e)}setEnableBlur(e){this.enableBlur!==e&&(this.enableBlur=e,this.calcLayout())}setLyricLines(e){this.lyricLines=e;const r=750;this.processedLines=e.map((s,a,h)=>{if(s.isBG)return{...s};{const i=h[a-1],n=h[a-2];if(i!=null&&i.isBG&&n){if(n.endTime<s.startTime)return{...s,startTime:Math.max(n.endTime,s.startTime-r)||s.startTime}}else if(i!=null&&i.endTime&&i.endTime<s.startTime)return{...s,startTime:Math.max(i==null?void 0:i.endTime,s.startTime-r)||s.startTime};return{...s}}}),this.processedLines.forEach((s,a,h)=>{const i=h[a+1],n=s.words[s.words.length-1];n&&P(n)&&(i?i.startTime>s.endTime&&(s.endTime=Math.min(s.endTime+1500,i.startTime)):s.endTime=s.endTime+1500)}),this.processedLines.forEach((s,a,h)=>{if(s.isBG)return;const i=h[a+1];i!=null&&i.isBG&&(i.startTime=Math.min(i.startTime,s.startTime))}),this.lyricLinesEl.forEach(s=>s.dispose()),this.lyricLinesEl=this.processedLines.map(s=>new G(this,s)),this.lyricLinesEl.forEach(s=>(this.element.appendChild(s.getElement()),s.updateMaskImage())),this.setLinePosXSpringParams({}),this.setLinePosYSpringParams({}),this.setLineScaleSpringParams({}),this.setCurrentTime(0,!0),this.calcLayout(!0)}calcLayout(e=!1){e&&(this.lyricLinesEl.forEach(o=>{const m=[o.getElement().clientWidth,o.getElement().clientHeight];this.lyricLinesSize.set(o,m),o.lineSize=m}),this.interludeDotsSize[0]=this.interludeDots.getElement().clientWidth,this.interludeDotsSize[1]=this.interludeDots.getElement().clientHeight);const r=.95;let a=-this.lyricLinesEl.slice(0,this.scrollToIndex).reduce((o,m)=>o+(m.getLine().isBG?0:this.lyricLinesSize.get(m)[1]),0);if(this.alignAnchor==="bottom"){a+=this.element.clientHeight/2;const o=this.lyricLinesEl[this.scrollToIndex];if(o){const m=this.lyricLinesSize.get(o)[1];a-=m/2}}else if(typeof this.alignAnchor=="number"){a+=this.element.clientHeight*this.alignAnchor;const o=this.lyricLinesEl[this.scrollToIndex];if(o){const m=this.lyricLinesSize.get(o)[1];a-=m/2}}const h=this.currentTime===0?void 0:this.getCurrentInterlude();let i=0;if(h&&(i=h[1]-h[0],i>=5e3)){const o=this.currentTime===0?this.lyricLinesEl[0]:this.lyricLinesEl[this.scrollToIndex+1];o&&(a-=this.lyricLinesSize.get(o)[1])}const n=Math.max(...this.bufferedLines);let c=0;this.lyricLinesEl.forEach((o,m)=>{const p=this.bufferedLines.has(m),g=p||m>=this.scrollToIndex&&m<n,u=o.getLine();let E=0;u.isDuet&&(E=this.size[0]-this.lyricLinesSize.get(o)[0]),m===this.scrollToIndex+1&&i>=5e3&&(this.interludeDots.setTransform(0,a),this.interludeDots.setInterlude(this.getCurrentInterlude()),a+=this.interludeDotsSize[1]),o.setTransform(E,a,g?1:r,p?1:1/3,this.enableBlur?3*(g?0:1+(m<this.scrollToIndex?Math.abs(this.scrollToIndex-m):Math.abs(m-Math.max(this.scrollToIndex,n)))):0,e,c),u.isBG&&g?a+=this.lyricLinesSize.get(o)[1]:u.isBG||(a+=this.lyricLinesSize.get(o)[1]),a>=0&&(c+=.05)})}getCurrentTime(){return this.currentTime}getLyrics(){return this.lyricLines}getElement(){return this.element}setCurrentTime(e,r=!1){this.currentTime=e,this.element.style.setProperty("--amll-player-time",`${e}`);const s=new Set,a=new Set,h=new Set;this.hotLines.forEach(i=>{const n=this.processedLines[i];if(!n.isBG)if(n){const c=this.processedLines[i+1];if(c!=null&&c.isBG){const o=Math.min(n.startTime,c==null?void 0:c.startTime),m=Math.max(n.endTime,c==null?void 0:c.endTime);(o>e||m<=e)&&(this.hotLines.delete(i),s.add(i),this.hotLines.delete(i+1),s.add(i+1),r&&(this.lyricLinesEl[i].disable(),this.lyricLinesEl[i+1].disable()))}else(n.startTime>e||n.endTime<=e)&&(this.hotLines.delete(i),s.add(i),r&&this.lyricLinesEl[i].disable())}else this.hotLines.delete(i),s.add(i),r&&this.lyricLinesEl[i].disable()}),this.processedLines.forEach((i,n,c)=>{var o;!i.isBG&&i.startTime<=e&&i.endTime>e&&(this.hotLines.has(n)||(this.hotLines.add(n),h.add(n),r&&this.lyricLinesEl[n].enable(),(o=c[n+1])!=null&&o.isBG&&(this.hotLines.add(n+1),h.add(n+1),r&&this.lyricLinesEl[n+1].enable())))}),this.bufferedLines.forEach(i=>{this.hotLines.has(i)||(a.add(i),r&&this.lyricLinesEl[i].disable())}),r?(this.bufferedLines.size>0?this.scrollToIndex=Math.min(...this.bufferedLines):this.scrollToIndex=this.processedLines.findIndex(i=>i.startTime>=e),this.bufferedLines.clear(),this.hotLines.forEach(i=>this.bufferedLines.add(i)),this.calcLayout(!0)):(a.size>0||h.size>0)&&(a.size===0&&h.size>0?(h.forEach(i=>{this.bufferedLines.add(i),this.lyricLinesEl[i].enable()}),this.scrollToIndex=Math.min(...this.bufferedLines)):h.size===0&&a.size>0?k(a,this.bufferedLines)&&this.bufferedLines.forEach(i=>{this.hotLines.has(i)||(this.bufferedLines.delete(i),this.lyricLinesEl[i].disable())}):(h.forEach(i=>{this.bufferedLines.add(i),this.lyricLinesEl[i].enable()}),a.forEach(i=>{this.bufferedLines.delete(i),this.lyricLinesEl[i].disable()}),this.bufferedLines.size>0&&(this.scrollToIndex=Math.min(...this.bufferedLines))),this.calcLayout())}update(e=0){const r=e/1e3;this.interludeDots.update(e),this.lyricLinesEl.forEach(s=>s.update(r))}setLinePosXSpringParams(e){this.posXSpringParams={...this.posXSpringParams,...e},this.lyricLinesEl.forEach(r=>r.lineTransforms.posX.updateParams(this.posXSpringParams))}setLinePosYSpringParams(e){this.posYSpringParams={...this.posYSpringParams,...e},this.lyricLinesEl.forEach(r=>r.lineTransforms.posY.updateParams(this.posYSpringParams))}setLineScaleSpringParams(e){this.scaleSpringParams={...this.scaleSpringParams,...e},this.lyricLinesEl.forEach(r=>r.lineTransforms.scale.updateParams(this.scaleSpringParams))}dispose(){this.element.remove(),this.resizeObserver.disconnect(),this.style.detach(),this.lyricLinesEl.forEach(e=>e.dispose()),window.removeEventListener("pageshow",this.onPageShow)}}exports.BackgroundRender=D;exports.LyricPlayer=Y;
|
|
@@ -0,0 +1,904 @@
|
|
|
1
|
+
var w = Object.defineProperty;
|
|
2
|
+
var v = (d, t, e) => t in d ? w(d, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : d[t] = e;
|
|
3
|
+
var l = (d, t, e) => (v(d, typeof t != "symbol" ? t + "" : t, e), e);
|
|
4
|
+
import { Container as x } from "@pixi/display";
|
|
5
|
+
import { Application as C } from "@pixi/app";
|
|
6
|
+
import { BlurFilter as f } from "@pixi/filter-blur";
|
|
7
|
+
import { ColorMatrixFilter as b } from "@pixi/filter-color-matrix";
|
|
8
|
+
import { Texture as M } from "@pixi/core";
|
|
9
|
+
import { Sprite as L } from "@pixi/sprite";
|
|
10
|
+
import { create as z } from "jss";
|
|
11
|
+
import I from "jss-preset-default";
|
|
12
|
+
class A extends x {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
l(this, "time", 0);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
class B {
|
|
19
|
+
constructor(t) {
|
|
20
|
+
l(this, "observer");
|
|
21
|
+
l(this, "app");
|
|
22
|
+
l(this, "curContainer");
|
|
23
|
+
l(this, "lastContainer", /* @__PURE__ */ new Set());
|
|
24
|
+
l(this, "onTick", (t) => {
|
|
25
|
+
for (const e of this.lastContainer)
|
|
26
|
+
e.alpha = Math.max(0, e.alpha - t / 60), e.alpha <= 0 && (this.app.stage.removeChild(e), this.lastContainer.delete(e));
|
|
27
|
+
if (this.curContainer) {
|
|
28
|
+
this.curContainer.alpha = Math.min(
|
|
29
|
+
1,
|
|
30
|
+
this.curContainer.alpha + t / 60
|
|
31
|
+
);
|
|
32
|
+
const [e, n, s, a] = this.curContainer.children, h = Math.max(this.app.screen.width, this.app.screen.height);
|
|
33
|
+
e.position.set(this.app.screen.width / 2, this.app.screen.height / 2), n.position.set(
|
|
34
|
+
this.app.screen.width / 2.5,
|
|
35
|
+
this.app.screen.height / 2.5
|
|
36
|
+
), s.position.set(this.app.screen.width / 2, this.app.screen.height / 2), a.position.set(this.app.screen.width / 2, this.app.screen.height / 2), e.width = h * Math.sqrt(2), e.height = e.width, n.width = h * 0.8, n.height = n.width, s.width = h * 0.5, s.height = s.width, a.width = h * 0.25, a.height = a.width, this.curContainer.time += t * this.flowSpeed, e.rotation += t / 1e3 * this.flowSpeed, n.rotation -= t / 500 * this.flowSpeed, s.rotation += t / 1e3 * this.flowSpeed, a.rotation -= t / 750 * this.flowSpeed, s.x = this.app.screen.width / 2 + this.app.screen.width / 4 * Math.cos(this.curContainer.time / 1e3 * 0.75), s.y = this.app.screen.height / 2 + this.app.screen.width / 4 * Math.cos(this.curContainer.time / 1e3 * 0.75), a.x = this.app.screen.width / 2 + this.app.screen.width / 4 * 0.1 + Math.cos(this.curContainer.time * 6e-3 * 0.75), a.y = this.app.screen.height / 2 + this.app.screen.width / 4 * 0.1 + Math.cos(this.curContainer.time * 6e-3 * 0.75);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
l(this, "flowSpeed", 2);
|
|
40
|
+
l(this, "currerntRenderScale", 0.75);
|
|
41
|
+
this.canvas = t;
|
|
42
|
+
const e = t.getBoundingClientRect();
|
|
43
|
+
this.canvas.width = e.width * this.currerntRenderScale, this.canvas.height = e.height * this.currerntRenderScale, this.observer = new ResizeObserver(() => {
|
|
44
|
+
const n = t.getBoundingClientRect();
|
|
45
|
+
this.canvas.width = Math.max(1, n.width), this.canvas.height = Math.max(1, n.height), this.app.renderer.resize(
|
|
46
|
+
this.canvas.width * this.currerntRenderScale,
|
|
47
|
+
this.canvas.height * this.currerntRenderScale
|
|
48
|
+
), this.rebuildFilters();
|
|
49
|
+
}), this.observer.observe(t), this.app = new C({
|
|
50
|
+
view: t,
|
|
51
|
+
resizeTo: this.canvas,
|
|
52
|
+
powerPreference: "low-power",
|
|
53
|
+
backgroundAlpha: 0
|
|
54
|
+
}), this.rebuildFilters(), this.app.ticker.add(this.onTick), this.app.ticker.start();
|
|
55
|
+
}
|
|
56
|
+
setRenderScale(t) {
|
|
57
|
+
this.currerntRenderScale = t;
|
|
58
|
+
const e = this.canvas.getBoundingClientRect();
|
|
59
|
+
this.canvas.width = Math.max(1, e.width), this.canvas.height = Math.max(1, e.height), this.app.renderer.resize(
|
|
60
|
+
this.canvas.width * this.currerntRenderScale,
|
|
61
|
+
this.canvas.height * this.currerntRenderScale
|
|
62
|
+
), this.rebuildFilters();
|
|
63
|
+
}
|
|
64
|
+
rebuildFilters() {
|
|
65
|
+
const t = Math.min(this.canvas.width, this.canvas.height), e = new b();
|
|
66
|
+
e.saturate(1.2, !1);
|
|
67
|
+
const n = new b();
|
|
68
|
+
n.brightness(0.6, !1);
|
|
69
|
+
const s = new b();
|
|
70
|
+
s.contrast(0.3, !0), this.app.stage.filters = [], this.app.stage.filters.push(new f(5, 1)), this.app.stage.filters.push(new f(10, 1)), this.app.stage.filters.push(new f(20, 2)), this.app.stage.filters.push(new f(40, 2)), t > 512 && this.app.stage.filters.push(new f(80, 2)), t > 768 && this.app.stage.filters.push(new f(160, 4)), t > 768 * 2 && this.app.stage.filters.push(new f(320, 4)), this.app.stage.filters.push(e, n, s), this.app.stage.filters.push(new f(5, 1));
|
|
71
|
+
}
|
|
72
|
+
setFPS(t) {
|
|
73
|
+
this.app.ticker.maxFPS = t;
|
|
74
|
+
}
|
|
75
|
+
pause() {
|
|
76
|
+
this.app.ticker.stop(), this.app.render();
|
|
77
|
+
}
|
|
78
|
+
resume() {
|
|
79
|
+
this.app.ticker.start();
|
|
80
|
+
}
|
|
81
|
+
async setAlbumImage(t) {
|
|
82
|
+
const e = await M.fromURL(t), n = new A(), s = new L(e), a = new L(e), h = new L(e), i = new L(e);
|
|
83
|
+
s.anchor.set(0.5, 0.5), a.anchor.set(0.5, 0.5), h.anchor.set(0.5, 0.5), i.anchor.set(0.5, 0.5), s.rotation = Math.random() * Math.PI * 2, a.rotation = Math.random() * Math.PI * 2, h.rotation = Math.random() * Math.PI * 2, i.rotation = Math.random() * Math.PI * 2, n.addChild(s, a, h, i), this.curContainer && this.lastContainer.add(this.curContainer), this.curContainer = n, this.app.stage.addChild(this.curContainer), this.curContainer.alpha = 0;
|
|
84
|
+
}
|
|
85
|
+
dispose() {
|
|
86
|
+
this.observer.disconnect(), this.app.ticker.remove(this.onTick);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
class Q extends B {
|
|
90
|
+
constructor() {
|
|
91
|
+
const e = document.createElement("canvas");
|
|
92
|
+
super(e);
|
|
93
|
+
l(this, "element");
|
|
94
|
+
this.element = e, e.style.pointerEvents = "none", e.style.zIndex = "-1";
|
|
95
|
+
}
|
|
96
|
+
getElement() {
|
|
97
|
+
return this.element;
|
|
98
|
+
}
|
|
99
|
+
dispose() {
|
|
100
|
+
super.dispose(), this.element.remove();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const D = (d, t) => d.size === t.size && [...d].every((e) => t.has(e));
|
|
104
|
+
function k(d) {
|
|
105
|
+
const e = 2.5949095;
|
|
106
|
+
return d < 0.5 ? Math.pow(2 * d, 2) * ((e + 1) * 2 * d - e) / 2 : (Math.pow(2 * d - 2, 2) * ((e + 1) * (d * 2 - 2) + e) + 2) / 2;
|
|
107
|
+
}
|
|
108
|
+
const y = (d, t, e) => Math.max(d, Math.min(t, e));
|
|
109
|
+
class $ {
|
|
110
|
+
constructor(t) {
|
|
111
|
+
l(this, "element", document.createElement("div"));
|
|
112
|
+
l(this, "dot0", document.createElement("span"));
|
|
113
|
+
l(this, "dot1", document.createElement("span"));
|
|
114
|
+
l(this, "dot2", document.createElement("span"));
|
|
115
|
+
l(this, "left", 0);
|
|
116
|
+
l(this, "top", 0);
|
|
117
|
+
l(this, "scale", 1);
|
|
118
|
+
l(this, "lastStyle", "");
|
|
119
|
+
l(this, "currentInterlude");
|
|
120
|
+
l(this, "currentTime", 0);
|
|
121
|
+
l(this, "targetBreatheDuration", 1500);
|
|
122
|
+
this.lyricPlayer = t, this.element.className = this.lyricPlayer.style.classes.interludeDots, this.element.appendChild(this.dot0), this.element.appendChild(this.dot1), this.element.appendChild(this.dot2);
|
|
123
|
+
}
|
|
124
|
+
getElement() {
|
|
125
|
+
return this.element;
|
|
126
|
+
}
|
|
127
|
+
setTransform(t = this.left, e = this.top) {
|
|
128
|
+
this.left = t, this.top = e, this.update();
|
|
129
|
+
}
|
|
130
|
+
setInterlude(t) {
|
|
131
|
+
this.currentInterlude = t, this.currentTime = (t == null ? void 0 : t[0]) ?? 0;
|
|
132
|
+
}
|
|
133
|
+
update(t = 0) {
|
|
134
|
+
this.currentTime += t;
|
|
135
|
+
let e = "";
|
|
136
|
+
if (e += `transform:translate(${this.left}px, ${this.top}px)`, this.currentInterlude) {
|
|
137
|
+
const n = this.currentInterlude[1] - this.currentInterlude[0], s = this.currentTime - this.currentInterlude[0];
|
|
138
|
+
if (s <= n) {
|
|
139
|
+
const a = n / Math.ceil(n / this.targetBreatheDuration);
|
|
140
|
+
let h = 1, i = 1;
|
|
141
|
+
h *= Math.sin(1.5 * Math.PI - s / a * 2) / 10 + 1, s < 1e3 && (h *= 1 - Math.pow((1e3 - s) / 1e3, 2)), s < 500 ? i = 0 : s < 1e3 && (i *= (s - 500) / 500), n - s < 750 && (h *= 1 - k(
|
|
142
|
+
(750 - (n - s)) / 750 / 2
|
|
143
|
+
)), n - s < 375 && (i *= y(
|
|
144
|
+
0,
|
|
145
|
+
(n - s) / 375,
|
|
146
|
+
1
|
|
147
|
+
)), h = Math.max(0, h), e += ` scale(${h})`;
|
|
148
|
+
const r = y(
|
|
149
|
+
0.25,
|
|
150
|
+
s * 3 / n * 0.75,
|
|
151
|
+
1
|
|
152
|
+
), c = y(
|
|
153
|
+
0.25,
|
|
154
|
+
(s - n / 3) * 3 / n * 0.75,
|
|
155
|
+
1
|
|
156
|
+
), o = y(
|
|
157
|
+
0.25,
|
|
158
|
+
(s - n / 3 * 2) * 3 / n * 0.75,
|
|
159
|
+
1
|
|
160
|
+
);
|
|
161
|
+
this.dot0.style.opacity = `${y(
|
|
162
|
+
0,
|
|
163
|
+
Math.max(0, i * r),
|
|
164
|
+
1
|
|
165
|
+
)}`, this.dot1.style.opacity = `${y(
|
|
166
|
+
0,
|
|
167
|
+
Math.max(0, i * c),
|
|
168
|
+
1
|
|
169
|
+
)}`, this.dot2.style.opacity = `${y(
|
|
170
|
+
0,
|
|
171
|
+
Math.max(0, i * o),
|
|
172
|
+
1
|
|
173
|
+
)}`;
|
|
174
|
+
} else
|
|
175
|
+
e += " scale(0)", this.dot0.style.opacity = "0", this.dot1.style.opacity = "0", this.dot2.style.opacity = "0";
|
|
176
|
+
} else
|
|
177
|
+
e += " scale(0)", this.dot0.style.opacity = "0", this.dot1.style.opacity = "0", this.dot2.style.opacity = "0";
|
|
178
|
+
e += ";", this.lastStyle !== e && (this.element.setAttribute("style", e), this.lastStyle = e);
|
|
179
|
+
}
|
|
180
|
+
dispose() {
|
|
181
|
+
this.element.remove();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
class S {
|
|
185
|
+
constructor(t = 0) {
|
|
186
|
+
l(this, "currentPosition", 0);
|
|
187
|
+
l(this, "targetPosition", 0);
|
|
188
|
+
l(this, "currentTime", 0);
|
|
189
|
+
l(this, "params", {});
|
|
190
|
+
l(this, "currentSolver");
|
|
191
|
+
l(this, "getV");
|
|
192
|
+
l(this, "queueParams");
|
|
193
|
+
l(this, "queuePosition");
|
|
194
|
+
this.targetPosition = t, this.currentPosition = this.targetPosition, this.currentSolver = () => this.targetPosition, this.getV = () => 0;
|
|
195
|
+
}
|
|
196
|
+
resetSolver() {
|
|
197
|
+
const t = this.getV(this.currentTime);
|
|
198
|
+
this.currentTime = 0, this.currentSolver = q(
|
|
199
|
+
this.currentPosition,
|
|
200
|
+
t,
|
|
201
|
+
this.targetPosition,
|
|
202
|
+
0,
|
|
203
|
+
this.params
|
|
204
|
+
), this.getV = W(this.currentSolver);
|
|
205
|
+
}
|
|
206
|
+
arrived() {
|
|
207
|
+
return Math.abs(this.targetPosition - this.currentPosition) < 0.01 && this.getV(this.currentTime) < 0.01 && this.queueParams === void 0 && this.queuePosition === void 0;
|
|
208
|
+
}
|
|
209
|
+
setPosition(t) {
|
|
210
|
+
this.targetPosition = t, this.currentPosition = t, this.currentSolver = () => this.targetPosition, this.getV = () => 0;
|
|
211
|
+
}
|
|
212
|
+
update(t = 0) {
|
|
213
|
+
this.currentTime += t, this.currentPosition = this.currentSolver(this.currentTime), this.queueParams && (this.queueParams.time -= t, this.queueParams.time <= 0 && this.updateParams({
|
|
214
|
+
...this.queueParams
|
|
215
|
+
})), this.queuePosition && (this.queuePosition.time -= t, this.queuePosition.time <= 0 && this.setTargetPosition(this.queuePosition.position)), this.arrived() && this.setPosition(this.targetPosition);
|
|
216
|
+
}
|
|
217
|
+
updateParams(t, e = 0) {
|
|
218
|
+
e > 0 ? this.queueParams = {
|
|
219
|
+
...t,
|
|
220
|
+
time: e
|
|
221
|
+
} : (this.params = {
|
|
222
|
+
...this.params,
|
|
223
|
+
...t
|
|
224
|
+
}, this.resetSolver());
|
|
225
|
+
}
|
|
226
|
+
setTargetPosition(t, e = 0) {
|
|
227
|
+
e > 0 ? this.queuePosition = {
|
|
228
|
+
position: t,
|
|
229
|
+
time: e
|
|
230
|
+
} : (this.queuePosition = void 0, this.targetPosition = t, this.resetSolver());
|
|
231
|
+
}
|
|
232
|
+
getCurrentPosition() {
|
|
233
|
+
return this.currentPosition;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function q(d, t, e, n = 0, s) {
|
|
237
|
+
const a = (s == null ? void 0 : s.soft) ?? !1, h = (s == null ? void 0 : s.stiffness) ?? 100, i = (s == null ? void 0 : s.damping) ?? 10, r = (s == null ? void 0 : s.mass) ?? 1, c = e - d;
|
|
238
|
+
if (a || 1 <= i / (2 * Math.sqrt(h * r))) {
|
|
239
|
+
const o = -Math.sqrt(h / r), m = -o * c - t;
|
|
240
|
+
return (p) => (p -= n, p < 0 ? d : e - (c + p * m) * Math.E ** (p * o));
|
|
241
|
+
} else {
|
|
242
|
+
const o = Math.sqrt(
|
|
243
|
+
4 * r * h - i ** 2
|
|
244
|
+
), m = (i * c - 2 * r * t) / o, p = 0.5 * o / r, g = -(0.5 * i) / r;
|
|
245
|
+
return (u) => (u -= n, u < 0 ? d : e - (Math.cos(u * p) * c + Math.sin(u * p) * m) * Math.E ** (u * g));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function R(d) {
|
|
249
|
+
return (e) => (d(e + 1e-3) - d(e - 1e-3)) / (2 * 1e-3);
|
|
250
|
+
}
|
|
251
|
+
function W(d) {
|
|
252
|
+
return R(d);
|
|
253
|
+
}
|
|
254
|
+
const T = /^[\p{Unified_Ideograph}\u0800-\u9FFC]+$/u;
|
|
255
|
+
function F(d, t = "rgba(0,0,0,1)", e = "rgba(0,0,0,0.5)") {
|
|
256
|
+
const n = 2 + d, s = d / n, a = (1 - s) / 2;
|
|
257
|
+
return [
|
|
258
|
+
`linear-gradient(to right,${t} ${a * 100}%,${e} ${(a + s) * 100}%)`,
|
|
259
|
+
s,
|
|
260
|
+
n
|
|
261
|
+
];
|
|
262
|
+
}
|
|
263
|
+
function P(d) {
|
|
264
|
+
return d.endTime - d.startTime >= 1e3 && d.word.length <= 7;
|
|
265
|
+
}
|
|
266
|
+
class O {
|
|
267
|
+
constructor(t, e = {
|
|
268
|
+
words: [],
|
|
269
|
+
translatedLyric: "",
|
|
270
|
+
romanLyric: "",
|
|
271
|
+
startTime: 0,
|
|
272
|
+
endTime: 0,
|
|
273
|
+
isBG: !1,
|
|
274
|
+
isDuet: !1
|
|
275
|
+
}) {
|
|
276
|
+
l(this, "element", document.createElement("div"));
|
|
277
|
+
l(this, "left", 0);
|
|
278
|
+
l(this, "top", 0);
|
|
279
|
+
l(this, "scale", 1);
|
|
280
|
+
l(this, "blur", 0);
|
|
281
|
+
l(this, "delay", 0);
|
|
282
|
+
l(this, "splittedWords", []);
|
|
283
|
+
// 由 LyricPlayer 来设置
|
|
284
|
+
l(this, "lineSize", [0, 0]);
|
|
285
|
+
l(this, "lineTransforms", {
|
|
286
|
+
posX: new S(0),
|
|
287
|
+
posY: new S(0),
|
|
288
|
+
scale: new S(1)
|
|
289
|
+
});
|
|
290
|
+
l(this, "_hide", !0);
|
|
291
|
+
l(this, "lastStyle", "");
|
|
292
|
+
this.lyricPlayer = t, this.lyricLine = e, this.element.setAttribute(
|
|
293
|
+
"class",
|
|
294
|
+
this.lyricPlayer.style.classes.lyricLine
|
|
295
|
+
), this.lyricLine.isBG && this.element.classList.add(this.lyricPlayer.style.classes.lyricBgLine), this.lyricLine.isDuet && this.element.classList.add(this.lyricPlayer.style.classes.lyricDuetLine), this.element.appendChild(document.createElement("div")), this.element.appendChild(document.createElement("div")), this.element.appendChild(document.createElement("div"));
|
|
296
|
+
const n = this.element.children[0], s = this.element.children[1], a = this.element.children[2];
|
|
297
|
+
n.setAttribute("class", this.lyricPlayer.style.classes.lyricMainLine), s.setAttribute("class", this.lyricPlayer.style.classes.lyricSubLine), a.setAttribute("class", this.lyricPlayer.style.classes.lyricSubLine), this.rebuildElement(), this.rebuildStyle();
|
|
298
|
+
}
|
|
299
|
+
enable() {
|
|
300
|
+
this.element.classList.add("active");
|
|
301
|
+
const t = this.element.children[0];
|
|
302
|
+
this.splittedWords.forEach((e) => {
|
|
303
|
+
e.elementAnimations.forEach((n) => {
|
|
304
|
+
n.currentTime = 0, n.playbackRate = 1, n.play();
|
|
305
|
+
});
|
|
306
|
+
}), t.classList.add("active");
|
|
307
|
+
}
|
|
308
|
+
disable() {
|
|
309
|
+
this.element.classList.remove("active");
|
|
310
|
+
const t = this.element.children[0];
|
|
311
|
+
this.splittedWords.forEach((e) => {
|
|
312
|
+
e.elementAnimations.forEach((n) => {
|
|
313
|
+
n.id === "float-word" && (n.playbackRate = -1, n.play());
|
|
314
|
+
});
|
|
315
|
+
}), t.classList.remove("active");
|
|
316
|
+
}
|
|
317
|
+
setLine(t) {
|
|
318
|
+
this.lyricLine = t, this.lyricLine.isBG ? this.element.classList.add(this.lyricPlayer.style.classes.lyricBgLine) : this.element.classList.remove(this.lyricPlayer.style.classes.lyricBgLine), this.lyricLine.isDuet ? this.element.classList.add(this.lyricPlayer.style.classes.lyricDuetLine) : this.element.classList.remove(
|
|
319
|
+
this.lyricPlayer.style.classes.lyricDuetLine
|
|
320
|
+
), this.rebuildElement(), this.rebuildStyle();
|
|
321
|
+
}
|
|
322
|
+
getLine() {
|
|
323
|
+
return this.lyricLine;
|
|
324
|
+
}
|
|
325
|
+
show() {
|
|
326
|
+
this._hide = !1, this.rebuildStyle();
|
|
327
|
+
}
|
|
328
|
+
hide() {
|
|
329
|
+
this._hide = !0, this.rebuildStyle();
|
|
330
|
+
}
|
|
331
|
+
rebuildStyle() {
|
|
332
|
+
if (this._hide) {
|
|
333
|
+
this.lastStyle !== "visibility:hidden;transform:translate(0,-10000px);" && (this.lastStyle = "visibility:hidden;transform:translate(0,-10000px);", this.element.setAttribute(
|
|
334
|
+
"style",
|
|
335
|
+
"visibility:hidden;transform:translate(0,-10000px);"
|
|
336
|
+
));
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
let t = `transform:translate(${this.lineTransforms.posX.getCurrentPosition()}px,${this.lineTransforms.posY.getCurrentPosition()}px) scale(${this.lineTransforms.scale.getCurrentPosition()});`;
|
|
340
|
+
this.lyricPlayer.disableSpring && this.isInSight && (t += `transition-delay:${this.delay}ms;`), t += `filter:blur(${Math.min(32, this.blur)}px);`, t !== this.lastStyle && (this.lastStyle = t, this.element.setAttribute("style", t));
|
|
341
|
+
}
|
|
342
|
+
rebuildElement() {
|
|
343
|
+
const t = this.element.children[0], e = this.element.children[1], n = this.element.children[2];
|
|
344
|
+
this.splittedWords = [], this.lyricLine.words.forEach((r) => {
|
|
345
|
+
if (T.test(r.word))
|
|
346
|
+
this.splittedWords.push({
|
|
347
|
+
...r,
|
|
348
|
+
width: 0,
|
|
349
|
+
height: 0,
|
|
350
|
+
elements: [],
|
|
351
|
+
elementAnimations: [],
|
|
352
|
+
shouldEmphasize: P(r)
|
|
353
|
+
});
|
|
354
|
+
else {
|
|
355
|
+
const c = /(\s*)(\S*)(\s*)/.exec(r.word);
|
|
356
|
+
c && (c[1].length > 0 && this.splittedWords.push({
|
|
357
|
+
word: " ",
|
|
358
|
+
startTime: 0,
|
|
359
|
+
endTime: 0,
|
|
360
|
+
width: 0,
|
|
361
|
+
height: 0,
|
|
362
|
+
elements: [],
|
|
363
|
+
elementAnimations: [],
|
|
364
|
+
shouldEmphasize: !1
|
|
365
|
+
}), this.splittedWords.push({
|
|
366
|
+
word: c[2],
|
|
367
|
+
startTime: r.startTime,
|
|
368
|
+
endTime: r.endTime,
|
|
369
|
+
width: 0,
|
|
370
|
+
height: 0,
|
|
371
|
+
elements: [],
|
|
372
|
+
elementAnimations: [],
|
|
373
|
+
shouldEmphasize: P(r)
|
|
374
|
+
}), c[3].length > 0 && this.splittedWords.push({
|
|
375
|
+
word: " ",
|
|
376
|
+
startTime: 0,
|
|
377
|
+
endTime: 0,
|
|
378
|
+
width: 0,
|
|
379
|
+
height: 0,
|
|
380
|
+
elements: [],
|
|
381
|
+
elementAnimations: [],
|
|
382
|
+
shouldEmphasize: !1
|
|
383
|
+
}));
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
const s = [], a = [];
|
|
387
|
+
function h(r) {
|
|
388
|
+
for (; r.firstChild; )
|
|
389
|
+
r.firstChild.nodeType === Node.ELEMENT_NODE ? s.push(t.firstChild) : r.firstChild.nodeType === Node.TEXT_NODE && a.push(t.firstChild), r.removeChild(r.firstChild), h(r.firstChild);
|
|
390
|
+
}
|
|
391
|
+
h(t);
|
|
392
|
+
let i = null;
|
|
393
|
+
this.splittedWords.forEach((r) => {
|
|
394
|
+
if (r.word.trim().length > 0)
|
|
395
|
+
if (r.shouldEmphasize) {
|
|
396
|
+
const c = s.pop() ?? document.createElement("span");
|
|
397
|
+
c.className = "emphasize", r.elements = [c];
|
|
398
|
+
for (const o of r.word) {
|
|
399
|
+
const m = s.pop() ?? document.createElement("span");
|
|
400
|
+
m.className = "", m.innerText = o, c.appendChild(m), r.elements.push(m);
|
|
401
|
+
}
|
|
402
|
+
if (r.elementAnimations = this.initEmphasizeAnimation(r), console.log(r.word, T.test(r.word)), i && !T.test(r.word))
|
|
403
|
+
if (i.childElementCount > 0)
|
|
404
|
+
i.appendChild(c);
|
|
405
|
+
else {
|
|
406
|
+
const o = s.pop() ?? document.createElement("span");
|
|
407
|
+
o.className = "", i.remove(), o.appendChild(i), o.appendChild(c), t.appendChild(o), i = o;
|
|
408
|
+
}
|
|
409
|
+
else
|
|
410
|
+
i = T.test(r.word) ? null : c, t.appendChild(c);
|
|
411
|
+
} else {
|
|
412
|
+
const c = s.pop() ?? document.createElement("span");
|
|
413
|
+
if (c.className = "", c.innerText = r.word, r.elements = [c], r.elementAnimations.push(this.initFloatAnimation(r, c)), i)
|
|
414
|
+
if (i.childElementCount > 0)
|
|
415
|
+
i.appendChild(c);
|
|
416
|
+
else {
|
|
417
|
+
const o = s.pop() ?? document.createElement("span");
|
|
418
|
+
o.className = "", i.remove(), o.appendChild(i), o.appendChild(c), t.appendChild(o), i = o;
|
|
419
|
+
}
|
|
420
|
+
else
|
|
421
|
+
i = c, t.appendChild(c);
|
|
422
|
+
}
|
|
423
|
+
else if (r.word.length > 0) {
|
|
424
|
+
const c = a.pop() ?? document.createTextNode(" ");
|
|
425
|
+
t.appendChild(c), i = null;
|
|
426
|
+
} else
|
|
427
|
+
i = null;
|
|
428
|
+
}), e.innerText = this.lyricLine.translatedLyric, n.innerText = this.lyricLine.romanLyric;
|
|
429
|
+
}
|
|
430
|
+
initFloatAnimation(t, e) {
|
|
431
|
+
const n = e.animate(
|
|
432
|
+
[
|
|
433
|
+
{
|
|
434
|
+
transform: "translateY(0px)"
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
transform: "translateY(-3%)"
|
|
438
|
+
}
|
|
439
|
+
],
|
|
440
|
+
{
|
|
441
|
+
duration: Math.max(1e3, t.endTime - t.startTime),
|
|
442
|
+
delay: t.startTime - this.lyricLine.startTime,
|
|
443
|
+
id: "float-word",
|
|
444
|
+
composite: "add",
|
|
445
|
+
fill: "both"
|
|
446
|
+
}
|
|
447
|
+
);
|
|
448
|
+
return n.pause(), n;
|
|
449
|
+
}
|
|
450
|
+
initEmphasizeAnimation(t) {
|
|
451
|
+
const e = t.startTime - this.lyricLine.startTime, n = t.endTime - t.startTime;
|
|
452
|
+
return t.elements.map((s, a, h) => {
|
|
453
|
+
if (a === 0)
|
|
454
|
+
return this.initFloatAnimation(t, s);
|
|
455
|
+
{
|
|
456
|
+
const i = s.animate(
|
|
457
|
+
[
|
|
458
|
+
{
|
|
459
|
+
offset: 0,
|
|
460
|
+
transform: "translate3d(0, 0px, 0px)",
|
|
461
|
+
filter: "drop-shadow(0 0 0 var(--amll-lyric-line-color))"
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
offset: 0.5,
|
|
465
|
+
transform: "translate3d(0, -2%, 20px)",
|
|
466
|
+
filter: "drop-shadow(0 0 0.2rem var(--amll-lyric-line-color))"
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
offset: 1,
|
|
470
|
+
transform: "translate3d(0, 0px, 0)",
|
|
471
|
+
filter: "drop-shadow(0 0 0 var(--amll-lyric-line-color))"
|
|
472
|
+
}
|
|
473
|
+
],
|
|
474
|
+
{
|
|
475
|
+
duration: Math.max(1e3, t.endTime - t.startTime),
|
|
476
|
+
delay: e + n / (h.length - 1) * (a - 1),
|
|
477
|
+
id: "glow-word",
|
|
478
|
+
iterations: 1,
|
|
479
|
+
composite: "replace",
|
|
480
|
+
fill: "both"
|
|
481
|
+
}
|
|
482
|
+
);
|
|
483
|
+
return i.pause(), i;
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
updateMaskImage() {
|
|
488
|
+
this.splittedWords.forEach((t) => {
|
|
489
|
+
const e = t.elements[0];
|
|
490
|
+
if (e) {
|
|
491
|
+
t.width = e.clientWidth, t.height = e.clientHeight;
|
|
492
|
+
const [n, s, a] = F(
|
|
493
|
+
16 / t.width,
|
|
494
|
+
"rgba(0,0,0,0.75)",
|
|
495
|
+
"rgba(0,0,0,0.25)"
|
|
496
|
+
), h = `${a * 100}% 100%`;
|
|
497
|
+
this.lyricPlayer.supportMaskImage ? (e.style.maskImage = n, e.style.maskOrigin = "left", e.style.maskSize = h) : (e.style.webkitMaskImage = n, e.style.webkitMaskOrigin = "left", e.style.webkitMaskSize = h);
|
|
498
|
+
const i = t.width + 16, r = `clamp(${-i}px,calc(${-i}px + (var(--amll-player-time) - ${t.startTime})*${i / Math.abs(t.endTime - t.startTime)}px),0px) 0px, left top`;
|
|
499
|
+
e.style.maskPosition = r, e.style.webkitMaskPosition = r;
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
getElement() {
|
|
504
|
+
return this.element;
|
|
505
|
+
}
|
|
506
|
+
setTransform(t = this.left, e = this.top, n = this.scale, s = 1, a = 0, h = !1, i = 0) {
|
|
507
|
+
this.left = t, this.top = e, this.scale = n, this.delay = i * 1e3 | 0;
|
|
508
|
+
const r = this.element.children[0];
|
|
509
|
+
r.style.opacity = `${s}`, h || this.lyricPlayer.disableSpring ? (this.blur = Math.min(32, a), h && this.element.classList.add(
|
|
510
|
+
this.lyricPlayer.style.classes.tmpDisableTransition
|
|
511
|
+
), this.lineTransforms.posX.setPosition(t), this.lineTransforms.posY.setPosition(e), this.lineTransforms.scale.setPosition(n), this.lyricPlayer.disableSpring ? this.show() : this.rebuildStyle(), h && requestAnimationFrame(() => {
|
|
512
|
+
this.element.classList.remove(
|
|
513
|
+
this.lyricPlayer.style.classes.tmpDisableTransition
|
|
514
|
+
);
|
|
515
|
+
})) : (this.lineTransforms.posX.setTargetPosition(t, i), this.lineTransforms.posY.setTargetPosition(e, i), this.lineTransforms.scale.setTargetPosition(n), this.blur !== Math.min(32, a) && (this.blur = Math.min(32, a), this.element.style.filter = `blur(${Math.min(32, a)}px)`));
|
|
516
|
+
}
|
|
517
|
+
update(t = 0) {
|
|
518
|
+
this.lyricPlayer.disableSpring || (this.lineTransforms.posX.update(t), this.lineTransforms.posY.update(t), this.lineTransforms.scale.update(t), this.isInSight ? this.show() : this.hide());
|
|
519
|
+
}
|
|
520
|
+
get isInSight() {
|
|
521
|
+
const t = this.lineTransforms.posX.getCurrentPosition(), e = this.lineTransforms.posY.getCurrentPosition(), n = t + this.lineSize[0], s = e + this.lineSize[1], a = this.lyricPlayer.pos[0], h = this.lyricPlayer.pos[1], i = this.lyricPlayer.pos[0] + this.lyricPlayer.size[0], r = this.lyricPlayer.pos[1] + this.lyricPlayer.size[1];
|
|
522
|
+
return !(t > i || e > r || n < a || s < h);
|
|
523
|
+
}
|
|
524
|
+
dispose() {
|
|
525
|
+
this.element.remove();
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
const G = z(I());
|
|
529
|
+
class Z extends EventTarget {
|
|
530
|
+
constructor() {
|
|
531
|
+
super();
|
|
532
|
+
l(this, "element", document.createElement("div"));
|
|
533
|
+
l(this, "currentTime", 0);
|
|
534
|
+
l(this, "lyricLines", []);
|
|
535
|
+
l(this, "processedLines", []);
|
|
536
|
+
l(this, "lyricLinesEl", []);
|
|
537
|
+
l(this, "lyricLinesSize", /* @__PURE__ */ new Map());
|
|
538
|
+
l(this, "hotLines", /* @__PURE__ */ new Set());
|
|
539
|
+
l(this, "bufferedLines", /* @__PURE__ */ new Set());
|
|
540
|
+
l(this, "scrollToIndex", 0);
|
|
541
|
+
l(this, "resizeObserver", new ResizeObserver((e) => {
|
|
542
|
+
const n = e[0].contentRect;
|
|
543
|
+
this.size[0] = n.width, this.size[1] = n.height, this.pos[0] = n.left, this.pos[1] = n.top, this.rebuildStyle(), this.calcLayout(!0), this.lyricLinesEl.forEach((s) => s.updateMaskImage());
|
|
544
|
+
}));
|
|
545
|
+
l(this, "posXSpringParams", {
|
|
546
|
+
mass: 1,
|
|
547
|
+
damping: 10,
|
|
548
|
+
stiffness: 100
|
|
549
|
+
});
|
|
550
|
+
l(this, "posYSpringParams", {
|
|
551
|
+
mass: 1,
|
|
552
|
+
damping: 15,
|
|
553
|
+
stiffness: 100
|
|
554
|
+
});
|
|
555
|
+
l(this, "scaleSpringParams", {
|
|
556
|
+
mass: 1,
|
|
557
|
+
damping: 20,
|
|
558
|
+
stiffness: 100
|
|
559
|
+
});
|
|
560
|
+
l(this, "enableBlur", !0);
|
|
561
|
+
l(this, "interludeDots");
|
|
562
|
+
l(this, "interludeDotsSize", [0, 0]);
|
|
563
|
+
l(this, "supportPlusLighter", CSS.supports("mix-blend-mode", "plus-lighter"));
|
|
564
|
+
l(this, "supportMaskImage", CSS.supports("mask-image", "none"));
|
|
565
|
+
l(this, "disableSpring", !1);
|
|
566
|
+
l(this, "alignAnchor", 0.5);
|
|
567
|
+
l(this, "size", [0, 0]);
|
|
568
|
+
l(this, "pos", [0, 0]);
|
|
569
|
+
l(this, "style", G.createStyleSheet({
|
|
570
|
+
lyricPlayer: {
|
|
571
|
+
userSelect: "none",
|
|
572
|
+
padding: "1rem",
|
|
573
|
+
boxSizing: "border-box",
|
|
574
|
+
fontSize: "max(5vh, 12px)",
|
|
575
|
+
fontWeight: "bold",
|
|
576
|
+
width: "100%",
|
|
577
|
+
height: "100%",
|
|
578
|
+
overflow: "hidden",
|
|
579
|
+
maxWidth: "100%",
|
|
580
|
+
maxHeight: "100%",
|
|
581
|
+
zIndex: 1,
|
|
582
|
+
color: "var(--amll-lyric-line-color)",
|
|
583
|
+
mixBlendMode: "plus-lighter",
|
|
584
|
+
contain: "strict"
|
|
585
|
+
},
|
|
586
|
+
lyricLine: {
|
|
587
|
+
position: "absolute",
|
|
588
|
+
transformOrigin: "left",
|
|
589
|
+
maxWidth: "65%",
|
|
590
|
+
padding: "max(2vh, 1rem) 1rem",
|
|
591
|
+
contain: "content",
|
|
592
|
+
transition: "filter 0.25s",
|
|
593
|
+
margin: "max(2vh, 1rem) -1rem"
|
|
594
|
+
},
|
|
595
|
+
"@media (max-width: 1024px)": {
|
|
596
|
+
lyricLine: {
|
|
597
|
+
maxWidth: "75%",
|
|
598
|
+
padding: "max(1vh, 1rem) 1rem",
|
|
599
|
+
margin: "0 -1rem"
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
lyricDuetLine: {
|
|
603
|
+
textAlign: "right",
|
|
604
|
+
transformOrigin: "right"
|
|
605
|
+
},
|
|
606
|
+
lyricBgLine: {
|
|
607
|
+
opacity: 0,
|
|
608
|
+
fontSize: "max(50%, 10px)",
|
|
609
|
+
transition: "opacity 0.25s",
|
|
610
|
+
"&.active": {
|
|
611
|
+
transition: "opacity 0.25s 0.25s",
|
|
612
|
+
opacity: 1
|
|
613
|
+
}
|
|
614
|
+
},
|
|
615
|
+
lyricMainLine: {
|
|
616
|
+
transition: "opacity 0.3s 0.25s",
|
|
617
|
+
margin: "-1rem",
|
|
618
|
+
padding: "1rem",
|
|
619
|
+
"& span": {
|
|
620
|
+
display: "inline-block",
|
|
621
|
+
margin: "-1rem",
|
|
622
|
+
padding: "1rem"
|
|
623
|
+
},
|
|
624
|
+
"& > span": {
|
|
625
|
+
whiteSpace: "pre-wrap",
|
|
626
|
+
wordBreak: "keep-all",
|
|
627
|
+
maxLines: "1",
|
|
628
|
+
"&.emphasize": {
|
|
629
|
+
margin: "-1rem",
|
|
630
|
+
padding: "1rem",
|
|
631
|
+
transformStyle: "preserve-3d",
|
|
632
|
+
perspective: "50vw"
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
},
|
|
636
|
+
lyricSubLine: {
|
|
637
|
+
fontSize: "max(50%, 10px)",
|
|
638
|
+
opacity: 0.5
|
|
639
|
+
},
|
|
640
|
+
disableSpring: {
|
|
641
|
+
"& > *": {
|
|
642
|
+
transition: "filter 0.25s, transform 0.5s"
|
|
643
|
+
}
|
|
644
|
+
},
|
|
645
|
+
interludeDots: {
|
|
646
|
+
height: "min(1rem,2.5vh)",
|
|
647
|
+
transformOrigin: "center",
|
|
648
|
+
width: "fit-content",
|
|
649
|
+
padding: "2.5% 0",
|
|
650
|
+
position: "absolute",
|
|
651
|
+
display: "flex",
|
|
652
|
+
gap: "0.5rem",
|
|
653
|
+
"& > *": {
|
|
654
|
+
width: "100%",
|
|
655
|
+
display: "inline-block",
|
|
656
|
+
borderRadius: "50%",
|
|
657
|
+
aspectRatio: "1 / 1",
|
|
658
|
+
backgroundColor: "var(--amll-lyric-line-color)",
|
|
659
|
+
marginRight: "4px"
|
|
660
|
+
},
|
|
661
|
+
"&.duet": {
|
|
662
|
+
right: "1rem",
|
|
663
|
+
transformOrigin: "center"
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
"@supports (mix-blend-mode: plus-lighter)": {
|
|
667
|
+
lyricSubLine: {
|
|
668
|
+
opacity: 0.3
|
|
669
|
+
}
|
|
670
|
+
},
|
|
671
|
+
tmpDisableTransition: {
|
|
672
|
+
transition: "none !important"
|
|
673
|
+
}
|
|
674
|
+
}));
|
|
675
|
+
l(this, "onPageShow", () => {
|
|
676
|
+
this.calcLayout(!0);
|
|
677
|
+
});
|
|
678
|
+
this.interludeDots = new $(this), this.element.setAttribute("class", this.style.classes.lyricPlayer), this.disableSpring && this.element.classList.add(this.style.classes.disableSpring), this.rebuildStyle(), this.resizeObserver.observe(this.element), this.element.appendChild(this.interludeDots.getElement()), this.style.attach(), this.interludeDots.setTransform(0, 200), window.addEventListener("pageshow", this.onPageShow);
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* 设置是否使用物理弹簧算法实现歌词动画效果,默认启用
|
|
682
|
+
*
|
|
683
|
+
* 如果启用,则会通过弹簧算法实时处理歌词位置,但是需要性能足够强劲的电脑方可流畅运行
|
|
684
|
+
*
|
|
685
|
+
* 如果不启用,则会回退到基于 `transition` 的过渡效果,对低性能的机器比较友好,但是效果会比较单一
|
|
686
|
+
*/
|
|
687
|
+
setEnableSpring(e = !0) {
|
|
688
|
+
this.disableSpring = !e, e ? this.element.classList.remove(this.style.classes.disableSpring) : this.element.classList.add(this.style.classes.disableSpring), this.calcLayout(!0);
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* 获取当前播放时间里是否处于间奏区间
|
|
692
|
+
* 如果是则会返回单位为毫秒的始末时间
|
|
693
|
+
* 否则返回 undefined
|
|
694
|
+
* @returns [开始时间,结束时间] 或 undefined 如果不处于间奏区间
|
|
695
|
+
*/
|
|
696
|
+
getCurrentInterlude() {
|
|
697
|
+
var s, a, h;
|
|
698
|
+
if (this.bufferedLines.size > 0)
|
|
699
|
+
return;
|
|
700
|
+
const e = this.currentTime + 20, n = this.scrollToIndex;
|
|
701
|
+
if (n === 0) {
|
|
702
|
+
if ((s = this.processedLines[0]) != null && s.startTime && this.processedLines[0].startTime > e)
|
|
703
|
+
return [0, this.processedLines[0].startTime];
|
|
704
|
+
} else if ((a = this.processedLines[n]) != null && a.endTime && ((h = this.processedLines[n + 1]) != null && h.startTime) && this.processedLines[n + 1].startTime > e && this.processedLines[n].endTime < e)
|
|
705
|
+
return [
|
|
706
|
+
this.processedLines[n].endTime,
|
|
707
|
+
this.processedLines[n + 1].startTime
|
|
708
|
+
];
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* 重建样式,这个只允许内部调用
|
|
712
|
+
*/
|
|
713
|
+
rebuildStyle() {
|
|
714
|
+
let e = "";
|
|
715
|
+
e += "--amll-lyric-player-width:", e += this.element.clientWidth, e += "px;", e += "--amll-lyric-player-height:", e += this.element.clientHeight, e += "px;", e += "--amll-lyric-line-color:", e += "#FFFFFF;", e += "--amll-player-time:", e += this.currentTime, e += ";", this.element.setAttribute("style", e);
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* 设置是否启用歌词行的模糊效果
|
|
719
|
+
* @param enable 是否启用
|
|
720
|
+
*/
|
|
721
|
+
setEnableBlur(e) {
|
|
722
|
+
this.enableBlur !== e && (this.enableBlur = e, this.calcLayout());
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* 设置当前播放歌词,要注意传入后这个数组内的信息不得修改,否则会发生错误
|
|
726
|
+
* @param lines 歌词数组
|
|
727
|
+
*/
|
|
728
|
+
setLyricLines(e) {
|
|
729
|
+
this.lyricLines = e;
|
|
730
|
+
const n = 750;
|
|
731
|
+
this.processedLines = e.map((s, a, h) => {
|
|
732
|
+
if (s.isBG)
|
|
733
|
+
return {
|
|
734
|
+
...s
|
|
735
|
+
};
|
|
736
|
+
{
|
|
737
|
+
const i = h[a - 1], r = h[a - 2];
|
|
738
|
+
if (i != null && i.isBG && r) {
|
|
739
|
+
if (r.endTime < s.startTime)
|
|
740
|
+
return {
|
|
741
|
+
...s,
|
|
742
|
+
startTime: Math.max(r.endTime, s.startTime - n) || s.startTime
|
|
743
|
+
};
|
|
744
|
+
} else if (i != null && i.endTime && i.endTime < s.startTime)
|
|
745
|
+
return {
|
|
746
|
+
...s,
|
|
747
|
+
startTime: Math.max(i == null ? void 0 : i.endTime, s.startTime - n) || s.startTime
|
|
748
|
+
};
|
|
749
|
+
return {
|
|
750
|
+
...s
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
}), this.processedLines.forEach((s, a, h) => {
|
|
754
|
+
const i = h[a + 1], r = s.words[s.words.length - 1];
|
|
755
|
+
r && P(r) && (i ? i.startTime > s.endTime && (s.endTime = Math.min(s.endTime + 1500, i.startTime)) : s.endTime = s.endTime + 1500);
|
|
756
|
+
}), this.processedLines.forEach((s, a, h) => {
|
|
757
|
+
if (s.isBG)
|
|
758
|
+
return;
|
|
759
|
+
const i = h[a + 1];
|
|
760
|
+
i != null && i.isBG && (i.startTime = Math.min(i.startTime, s.startTime));
|
|
761
|
+
}), this.lyricLinesEl.forEach((s) => s.dispose()), this.lyricLinesEl = this.processedLines.map(
|
|
762
|
+
(s) => new O(this, s)
|
|
763
|
+
), this.lyricLinesEl.forEach(
|
|
764
|
+
(s) => (this.element.appendChild(s.getElement()), s.updateMaskImage())
|
|
765
|
+
), this.setLinePosXSpringParams({}), this.setLinePosYSpringParams({}), this.setLineScaleSpringParams({}), this.setCurrentTime(0, !0), this.calcLayout(!0);
|
|
766
|
+
}
|
|
767
|
+
calcLayout(e = !1) {
|
|
768
|
+
e && (this.lyricLinesEl.forEach((o) => {
|
|
769
|
+
const m = [
|
|
770
|
+
o.getElement().clientWidth,
|
|
771
|
+
o.getElement().clientHeight
|
|
772
|
+
];
|
|
773
|
+
this.lyricLinesSize.set(o, m), o.lineSize = m;
|
|
774
|
+
}), this.interludeDotsSize[0] = this.interludeDots.getElement().clientWidth, this.interludeDotsSize[1] = this.interludeDots.getElement().clientHeight);
|
|
775
|
+
const n = 0.95;
|
|
776
|
+
let a = -this.lyricLinesEl.slice(0, this.scrollToIndex).reduce(
|
|
777
|
+
(o, m) => o + (m.getLine().isBG ? 0 : this.lyricLinesSize.get(m)[1]),
|
|
778
|
+
0
|
|
779
|
+
);
|
|
780
|
+
if (this.alignAnchor === "bottom") {
|
|
781
|
+
a += this.element.clientHeight / 2;
|
|
782
|
+
const o = this.lyricLinesEl[this.scrollToIndex];
|
|
783
|
+
if (o) {
|
|
784
|
+
const m = this.lyricLinesSize.get(o)[1];
|
|
785
|
+
a -= m / 2;
|
|
786
|
+
}
|
|
787
|
+
} else if (typeof this.alignAnchor == "number") {
|
|
788
|
+
a += this.element.clientHeight * this.alignAnchor;
|
|
789
|
+
const o = this.lyricLinesEl[this.scrollToIndex];
|
|
790
|
+
if (o) {
|
|
791
|
+
const m = this.lyricLinesSize.get(o)[1];
|
|
792
|
+
a -= m / 2;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
const h = this.currentTime === 0 ? void 0 : this.getCurrentInterlude();
|
|
796
|
+
let i = 0;
|
|
797
|
+
if (h && (i = h[1] - h[0], i >= 5e3)) {
|
|
798
|
+
const o = this.currentTime === 0 ? this.lyricLinesEl[0] : this.lyricLinesEl[this.scrollToIndex + 1];
|
|
799
|
+
o && (a -= this.lyricLinesSize.get(o)[1]);
|
|
800
|
+
}
|
|
801
|
+
const r = Math.max(...this.bufferedLines);
|
|
802
|
+
let c = 0;
|
|
803
|
+
this.lyricLinesEl.forEach((o, m) => {
|
|
804
|
+
const p = this.bufferedLines.has(m), g = p || m >= this.scrollToIndex && m < r, u = o.getLine();
|
|
805
|
+
let E = 0;
|
|
806
|
+
u.isDuet && (E = this.size[0] - this.lyricLinesSize.get(o)[0]), m === this.scrollToIndex + 1 && i >= 5e3 && (this.interludeDots.setTransform(0, a), this.interludeDots.setInterlude(this.getCurrentInterlude()), a += this.interludeDotsSize[1]), o.setTransform(
|
|
807
|
+
E,
|
|
808
|
+
a,
|
|
809
|
+
g ? 1 : n,
|
|
810
|
+
p ? 1 : 1 / 3,
|
|
811
|
+
this.enableBlur ? 3 * (g ? 0 : 1 + (m < this.scrollToIndex ? Math.abs(this.scrollToIndex - m) : Math.abs(m - Math.max(this.scrollToIndex, r)))) : 0,
|
|
812
|
+
e,
|
|
813
|
+
c
|
|
814
|
+
), u.isBG && g ? a += this.lyricLinesSize.get(o)[1] : u.isBG || (a += this.lyricLinesSize.get(o)[1]), a >= 0 && (c += 0.05);
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
getCurrentTime() {
|
|
818
|
+
return this.currentTime;
|
|
819
|
+
}
|
|
820
|
+
getLyrics() {
|
|
821
|
+
return this.lyricLines;
|
|
822
|
+
}
|
|
823
|
+
getElement() {
|
|
824
|
+
return this.element;
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* 设置当前播放进度,单位为毫秒且**必须是整数**,此时将会更新内部的歌词进度信息
|
|
828
|
+
* 内部会根据调用间隔和播放进度自动决定如何滚动和显示歌词,所以这个的调用频率越快越准确越好
|
|
829
|
+
*
|
|
830
|
+
* 调用完成后,可以每帧调用 `update` 函数来执行歌词动画效果
|
|
831
|
+
* @param time 当前播放进度,单位为毫秒
|
|
832
|
+
*/
|
|
833
|
+
setCurrentTime(e, n = !1) {
|
|
834
|
+
this.currentTime = e, this.element.style.setProperty("--amll-player-time", `${e}`);
|
|
835
|
+
const s = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), h = /* @__PURE__ */ new Set();
|
|
836
|
+
this.hotLines.forEach((i) => {
|
|
837
|
+
const r = this.processedLines[i];
|
|
838
|
+
if (!r.isBG)
|
|
839
|
+
if (r) {
|
|
840
|
+
const c = this.processedLines[i + 1];
|
|
841
|
+
if (c != null && c.isBG) {
|
|
842
|
+
const o = Math.min(r.startTime, c == null ? void 0 : c.startTime), m = Math.max(r.endTime, c == null ? void 0 : c.endTime);
|
|
843
|
+
(o > e || m <= e) && (this.hotLines.delete(i), s.add(i), this.hotLines.delete(i + 1), s.add(i + 1), n && (this.lyricLinesEl[i].disable(), this.lyricLinesEl[i + 1].disable()));
|
|
844
|
+
} else
|
|
845
|
+
(r.startTime > e || r.endTime <= e) && (this.hotLines.delete(i), s.add(i), n && this.lyricLinesEl[i].disable());
|
|
846
|
+
} else
|
|
847
|
+
this.hotLines.delete(i), s.add(i), n && this.lyricLinesEl[i].disable();
|
|
848
|
+
}), this.processedLines.forEach((i, r, c) => {
|
|
849
|
+
var o;
|
|
850
|
+
!i.isBG && i.startTime <= e && i.endTime > e && (this.hotLines.has(r) || (this.hotLines.add(r), h.add(r), n && this.lyricLinesEl[r].enable(), (o = c[r + 1]) != null && o.isBG && (this.hotLines.add(r + 1), h.add(r + 1), n && this.lyricLinesEl[r + 1].enable())));
|
|
851
|
+
}), this.bufferedLines.forEach((i) => {
|
|
852
|
+
this.hotLines.has(i) || (a.add(i), n && this.lyricLinesEl[i].disable());
|
|
853
|
+
}), n ? (this.bufferedLines.size > 0 ? this.scrollToIndex = Math.min(...this.bufferedLines) : this.scrollToIndex = this.processedLines.findIndex(
|
|
854
|
+
(i) => i.startTime >= e
|
|
855
|
+
), this.bufferedLines.clear(), this.hotLines.forEach((i) => this.bufferedLines.add(i)), this.calcLayout(!0)) : (a.size > 0 || h.size > 0) && (a.size === 0 && h.size > 0 ? (h.forEach((i) => {
|
|
856
|
+
this.bufferedLines.add(i), this.lyricLinesEl[i].enable();
|
|
857
|
+
}), this.scrollToIndex = Math.min(...this.bufferedLines)) : h.size === 0 && a.size > 0 ? D(a, this.bufferedLines) && this.bufferedLines.forEach((i) => {
|
|
858
|
+
this.hotLines.has(i) || (this.bufferedLines.delete(i), this.lyricLinesEl[i].disable());
|
|
859
|
+
}) : (h.forEach((i) => {
|
|
860
|
+
this.bufferedLines.add(i), this.lyricLinesEl[i].enable();
|
|
861
|
+
}), a.forEach((i) => {
|
|
862
|
+
this.bufferedLines.delete(i), this.lyricLinesEl[i].disable();
|
|
863
|
+
}), this.bufferedLines.size > 0 && (this.scrollToIndex = Math.min(...this.bufferedLines))), this.calcLayout());
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* 更新动画,这个函数应该被逐帧调用
|
|
867
|
+
* @param delta 距离上一次被调用到现在的时长,单位为毫秒(可为浮点数)
|
|
868
|
+
*/
|
|
869
|
+
update(e = 0) {
|
|
870
|
+
const n = e / 1e3;
|
|
871
|
+
this.interludeDots.update(e), this.lyricLinesEl.forEach((s) => s.update(n));
|
|
872
|
+
}
|
|
873
|
+
setLinePosXSpringParams(e) {
|
|
874
|
+
this.posXSpringParams = {
|
|
875
|
+
...this.posXSpringParams,
|
|
876
|
+
...e
|
|
877
|
+
}, this.lyricLinesEl.forEach(
|
|
878
|
+
(n) => n.lineTransforms.posX.updateParams(this.posXSpringParams)
|
|
879
|
+
);
|
|
880
|
+
}
|
|
881
|
+
setLinePosYSpringParams(e) {
|
|
882
|
+
this.posYSpringParams = {
|
|
883
|
+
...this.posYSpringParams,
|
|
884
|
+
...e
|
|
885
|
+
}, this.lyricLinesEl.forEach(
|
|
886
|
+
(n) => n.lineTransforms.posY.updateParams(this.posYSpringParams)
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
setLineScaleSpringParams(e) {
|
|
890
|
+
this.scaleSpringParams = {
|
|
891
|
+
...this.scaleSpringParams,
|
|
892
|
+
...e
|
|
893
|
+
}, this.lyricLinesEl.forEach(
|
|
894
|
+
(n) => n.lineTransforms.scale.updateParams(this.scaleSpringParams)
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
dispose() {
|
|
898
|
+
this.element.remove(), this.resizeObserver.disconnect(), this.style.detach(), this.lyricLinesEl.forEach((e) => e.dispose()), window.removeEventListener("pageshow", this.onPageShow);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
export {
|
|
902
|
+
Q as BackgroundRender,
|
|
903
|
+
Z as LyricPlayer
|
|
904
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview
|
|
3
|
+
* 一个播放歌词的组件
|
|
4
|
+
* @author SteveXMH
|
|
5
|
+
*/
|
|
6
|
+
import type { HasElement, Disposable } from "../interfaces";
|
|
7
|
+
import { PixiRenderer } from "./pixi-renderer";
|
|
8
|
+
export declare class BackgroundRender extends PixiRenderer implements HasElement, Disposable {
|
|
9
|
+
private element;
|
|
10
|
+
constructor();
|
|
11
|
+
getElement(): HTMLCanvasElement;
|
|
12
|
+
dispose(): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Disposable } from "../interfaces";
|
|
2
|
+
export declare class PixiRenderer implements Disposable {
|
|
3
|
+
private canvas;
|
|
4
|
+
private observer;
|
|
5
|
+
private app;
|
|
6
|
+
private curContainer?;
|
|
7
|
+
private lastContainer;
|
|
8
|
+
private onTick;
|
|
9
|
+
flowSpeed: number;
|
|
10
|
+
private currerntRenderScale;
|
|
11
|
+
constructor(canvas: HTMLCanvasElement);
|
|
12
|
+
setRenderScale(scale: number): void;
|
|
13
|
+
rebuildFilters(): void;
|
|
14
|
+
setFPS(fps: number): void;
|
|
15
|
+
pause(): void;
|
|
16
|
+
resume(): void;
|
|
17
|
+
setAlbumImage(albumUrl: string): Promise<void>;
|
|
18
|
+
dispose(): void;
|
|
19
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 拥有一个 HTML 元素的接口
|
|
3
|
+
*
|
|
4
|
+
* 可以通过 `getElement` 获取这个类所对应的 HTML 元素实例
|
|
5
|
+
*/
|
|
6
|
+
export interface HasElement {
|
|
7
|
+
/** 获取这个类所对应的 HTML 元素实例 */
|
|
8
|
+
getElement(): HTMLElement;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 实现了这个接口的东西需要在使用完毕后
|
|
12
|
+
*
|
|
13
|
+
* 手动调用 `dispose` 函数来销毁清除占用资源
|
|
14
|
+
*
|
|
15
|
+
* 以免产生泄露
|
|
16
|
+
*/
|
|
17
|
+
export interface Disposable {
|
|
18
|
+
/**
|
|
19
|
+
* 销毁实现了该接口的对象实例,释放占用的资源
|
|
20
|
+
*
|
|
21
|
+
* 一般情况下,调用本函数后就不可以再调用对象的任何函数了
|
|
22
|
+
*/
|
|
23
|
+
dispose(): void;
|
|
24
|
+
}
|
|
25
|
+
/** 一个歌词单词 */
|
|
26
|
+
export interface LyricWord {
|
|
27
|
+
/** 单词的起始时间 */
|
|
28
|
+
startTime: number;
|
|
29
|
+
/** 单词的结束时间 */
|
|
30
|
+
endTime: number;
|
|
31
|
+
/** 单词 */
|
|
32
|
+
word: string;
|
|
33
|
+
}
|
|
34
|
+
/** 一行歌词,存储多个单词 */
|
|
35
|
+
export interface LyricLine {
|
|
36
|
+
/**
|
|
37
|
+
* 该行的所有单词
|
|
38
|
+
* 如果是 LyRiC 等只能表达一行歌词的格式,这里就只会有一个单词
|
|
39
|
+
*/
|
|
40
|
+
words: LyricWord[];
|
|
41
|
+
translatedLyric: string;
|
|
42
|
+
romanLyric: string;
|
|
43
|
+
/** 句子的起始时间 */
|
|
44
|
+
startTime: number;
|
|
45
|
+
/** 句子的结束时间 */
|
|
46
|
+
endTime: number;
|
|
47
|
+
/** 该行是否为背景歌词行 */
|
|
48
|
+
isBG: boolean;
|
|
49
|
+
/** 该行是否为对唱歌词行(即歌词行靠右对齐) */
|
|
50
|
+
isDuet: boolean;
|
|
51
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview
|
|
3
|
+
* 一个播放歌词的组件
|
|
4
|
+
* @author SteveXMH
|
|
5
|
+
*/
|
|
6
|
+
import type { Disposable, HasElement, LyricLine } from "../interfaces";
|
|
7
|
+
import { SpringParams } from "../utils/spring";
|
|
8
|
+
/**
|
|
9
|
+
* 一个播放歌词的组件
|
|
10
|
+
*/
|
|
11
|
+
export declare class LyricPlayer extends EventTarget implements HasElement, Disposable {
|
|
12
|
+
private element;
|
|
13
|
+
private currentTime;
|
|
14
|
+
private lyricLines;
|
|
15
|
+
private processedLines;
|
|
16
|
+
private lyricLinesEl;
|
|
17
|
+
private lyricLinesSize;
|
|
18
|
+
private hotLines;
|
|
19
|
+
private bufferedLines;
|
|
20
|
+
private scrollToIndex;
|
|
21
|
+
private resizeObserver;
|
|
22
|
+
private posXSpringParams;
|
|
23
|
+
private posYSpringParams;
|
|
24
|
+
private scaleSpringParams;
|
|
25
|
+
private enableBlur;
|
|
26
|
+
private interludeDots;
|
|
27
|
+
private interludeDotsSize;
|
|
28
|
+
readonly supportPlusLighter: boolean;
|
|
29
|
+
readonly supportMaskImage: boolean;
|
|
30
|
+
disableSpring: boolean;
|
|
31
|
+
alignAnchor: "top" | "bottom" | number;
|
|
32
|
+
readonly size: [number, number];
|
|
33
|
+
readonly pos: [number, number];
|
|
34
|
+
/**
|
|
35
|
+
* 设置是否使用物理弹簧算法实现歌词动画效果,默认启用
|
|
36
|
+
*
|
|
37
|
+
* 如果启用,则会通过弹簧算法实时处理歌词位置,但是需要性能足够强劲的电脑方可流畅运行
|
|
38
|
+
*
|
|
39
|
+
* 如果不启用,则会回退到基于 `transition` 的过渡效果,对低性能的机器比较友好,但是效果会比较单一
|
|
40
|
+
*/
|
|
41
|
+
setEnableSpring(enable?: boolean): void;
|
|
42
|
+
readonly style: import("jss").StyleSheet<"lyricPlayer" | "lyricLine" | "@media (max-width: 1024px)" | "lyricDuetLine" | "lyricBgLine" | "lyricMainLine" | "lyricSubLine" | "disableSpring" | "interludeDots" | "@supports (mix-blend-mode: plus-lighter)" | "tmpDisableTransition">;
|
|
43
|
+
private onPageShow;
|
|
44
|
+
constructor();
|
|
45
|
+
/**
|
|
46
|
+
* 获取当前播放时间里是否处于间奏区间
|
|
47
|
+
* 如果是则会返回单位为毫秒的始末时间
|
|
48
|
+
* 否则返回 undefined
|
|
49
|
+
* @returns [开始时间,结束时间] 或 undefined 如果不处于间奏区间
|
|
50
|
+
*/
|
|
51
|
+
getCurrentInterlude(): [number, number] | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* 重建样式,这个只允许内部调用
|
|
54
|
+
*/
|
|
55
|
+
rebuildStyle(): void;
|
|
56
|
+
/**
|
|
57
|
+
* 设置是否启用歌词行的模糊效果
|
|
58
|
+
* @param enable 是否启用
|
|
59
|
+
*/
|
|
60
|
+
setEnableBlur(enable: boolean): void;
|
|
61
|
+
/**
|
|
62
|
+
* 设置当前播放歌词,要注意传入后这个数组内的信息不得修改,否则会发生错误
|
|
63
|
+
* @param lines 歌词数组
|
|
64
|
+
*/
|
|
65
|
+
setLyricLines(lines: LyricLine[]): void;
|
|
66
|
+
calcLayout(reflow?: boolean): void;
|
|
67
|
+
getCurrentTime(): number;
|
|
68
|
+
getLyrics(): LyricLine[];
|
|
69
|
+
getElement(): HTMLElement;
|
|
70
|
+
/**
|
|
71
|
+
* 设置当前播放进度,单位为毫秒且**必须是整数**,此时将会更新内部的歌词进度信息
|
|
72
|
+
* 内部会根据调用间隔和播放进度自动决定如何滚动和显示歌词,所以这个的调用频率越快越准确越好
|
|
73
|
+
*
|
|
74
|
+
* 调用完成后,可以每帧调用 `update` 函数来执行歌词动画效果
|
|
75
|
+
* @param time 当前播放进度,单位为毫秒
|
|
76
|
+
*/
|
|
77
|
+
setCurrentTime(time: number, isSeek?: boolean): void;
|
|
78
|
+
/**
|
|
79
|
+
* 更新动画,这个函数应该被逐帧调用
|
|
80
|
+
* @param delta 距离上一次被调用到现在的时长,单位为毫秒(可为浮点数)
|
|
81
|
+
*/
|
|
82
|
+
update(delta?: number): void;
|
|
83
|
+
setLinePosXSpringParams(params: Partial<SpringParams>): void;
|
|
84
|
+
setLinePosYSpringParams(params: Partial<SpringParams>): void;
|
|
85
|
+
setLineScaleSpringParams(params: Partial<SpringParams>): void;
|
|
86
|
+
dispose(): void;
|
|
87
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { LyricPlayer } from ".";
|
|
2
|
+
import type { Disposable, HasElement } from "../interfaces";
|
|
3
|
+
export declare class InterludeDots implements HasElement, Disposable {
|
|
4
|
+
private readonly lyricPlayer;
|
|
5
|
+
private element;
|
|
6
|
+
private dot0;
|
|
7
|
+
private dot1;
|
|
8
|
+
private dot2;
|
|
9
|
+
private left;
|
|
10
|
+
private top;
|
|
11
|
+
private scale;
|
|
12
|
+
private lastStyle;
|
|
13
|
+
private currentInterlude?;
|
|
14
|
+
private currentTime;
|
|
15
|
+
private targetBreatheDuration;
|
|
16
|
+
constructor(lyricPlayer: LyricPlayer);
|
|
17
|
+
getElement(): HTMLElement;
|
|
18
|
+
setTransform(left?: number, top?: number): void;
|
|
19
|
+
setInterlude(interlude?: [number, number]): void;
|
|
20
|
+
update(delta?: number): void;
|
|
21
|
+
dispose(): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { LyricPlayer } from ".";
|
|
2
|
+
import { Disposable, HasElement, LyricLine, LyricWord } from "../interfaces";
|
|
3
|
+
import { Spring } from "../utils/spring";
|
|
4
|
+
export declare function shouldEmphasize(word: LyricWord): boolean;
|
|
5
|
+
export declare class LyricLineEl implements HasElement, Disposable {
|
|
6
|
+
private lyricPlayer;
|
|
7
|
+
private lyricLine;
|
|
8
|
+
private element;
|
|
9
|
+
private left;
|
|
10
|
+
private top;
|
|
11
|
+
private scale;
|
|
12
|
+
private blur;
|
|
13
|
+
private delay;
|
|
14
|
+
private splittedWords;
|
|
15
|
+
lineSize: number[];
|
|
16
|
+
readonly lineTransforms: {
|
|
17
|
+
posX: Spring;
|
|
18
|
+
posY: Spring;
|
|
19
|
+
scale: Spring;
|
|
20
|
+
};
|
|
21
|
+
constructor(lyricPlayer: LyricPlayer, lyricLine?: LyricLine);
|
|
22
|
+
enable(): void;
|
|
23
|
+
disable(): void;
|
|
24
|
+
setLine(line: LyricLine): void;
|
|
25
|
+
getLine(): LyricLine;
|
|
26
|
+
private _hide;
|
|
27
|
+
private lastStyle;
|
|
28
|
+
show(): void;
|
|
29
|
+
hide(): void;
|
|
30
|
+
rebuildStyle(): void;
|
|
31
|
+
rebuildElement(): void;
|
|
32
|
+
private initFloatAnimation;
|
|
33
|
+
private initEmphasizeAnimation;
|
|
34
|
+
updateMaskImage(): void;
|
|
35
|
+
getElement(): HTMLElement;
|
|
36
|
+
setTransform(left?: number, top?: number, scale?: number, opacity?: number, blur?: number, force?: boolean, delay?: number): void;
|
|
37
|
+
update(delta?: number): void;
|
|
38
|
+
get isInSight(): boolean;
|
|
39
|
+
dispose(): void;
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const eqSet: <T>(xs: Set<T>, ys: Set<T>) => boolean;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** MIT License github.com/pushkine/ */
|
|
2
|
+
export interface SpringParams {
|
|
3
|
+
mass: number;
|
|
4
|
+
damping: number;
|
|
5
|
+
stiffness: number;
|
|
6
|
+
soft: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class Spring {
|
|
9
|
+
private currentPosition;
|
|
10
|
+
private targetPosition;
|
|
11
|
+
private currentTime;
|
|
12
|
+
private params;
|
|
13
|
+
private currentSolver;
|
|
14
|
+
private getV;
|
|
15
|
+
private queueParams;
|
|
16
|
+
private queuePosition;
|
|
17
|
+
constructor(currentPosition?: number);
|
|
18
|
+
private resetSolver;
|
|
19
|
+
arrived(): boolean;
|
|
20
|
+
setPosition(targetPosition: number): void;
|
|
21
|
+
update(delta?: number): void;
|
|
22
|
+
updateParams(params: Partial<SpringParams>, delay?: number): void;
|
|
23
|
+
setTargetPosition(targetPosition: number, delay?: number): void;
|
|
24
|
+
getCurrentPosition(): number;
|
|
25
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@applemusic-like-lyrics/core",
|
|
3
|
+
"packageManager": "yarn@3.6.1",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
8
|
+
"main": "./dist/amll-core.cjs",
|
|
9
|
+
"module": "./dist/amll-core.mjs",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/amll-core.mjs",
|
|
13
|
+
"require": "./dist/amll-core.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/stats.js": "^0.17.0",
|
|
18
|
+
"lil-gui": "^0.18.2",
|
|
19
|
+
"rome": "^12.1.3",
|
|
20
|
+
"stats.js": "^0.17.0",
|
|
21
|
+
"vite": "^4.4.6",
|
|
22
|
+
"vite-plugin-dts": "^3.3.1"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"jss": "^10.10.0",
|
|
26
|
+
"jss-preset-default": "^10.10.0",
|
|
27
|
+
"pixi.js": "^7.2.4"
|
|
28
|
+
}
|
|
29
|
+
}
|