@applemusic-like-lyrics/core 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"amll-core.mjs","names":["meshVertShader","meshFragShader","styles","styles","styles","styles","styles","styles"],"sources":["../src/bg-render/base.ts","../src/utils/resource.ts","../src/bg-render/img.ts","../src/utils/clamp.ts","../src/bg-render/mesh-renderer/cp-presets.ts","../src/bg-render/mesh-renderer/cp-generate.ts","../src/bg-render/mesh-renderer/index.ts","../src/bg-render/pixi-renderer.ts","../src/bg-render/index.ts","../src/styles/lyric-player.module.css","../src/utils/optimize-lyric.ts","../src/lyric-player/dom/interlude-dots.ts","../src/utils/schedule.ts","../src/utils/derivative.ts","../src/utils/spring.ts","../src/lyric-player/base/bottom-line.ts","../src/lyric-player/base/consts.ts","../src/lyric-player/base/layout.ts","../src/lyric-player/base/scroll.ts","../src/utils/eq-set.ts","../src/lyric-player/base/timeline.ts","../src/lyric-player/base/index.ts","../src/lyric-player/base/group.ts","../src/lyric-player/dom/lyric-group.ts","../src/utils/is-cjk.ts","../src/lyric-player/base/line.ts","../src/utils/lyric-line-break.ts","../src/utils/line-balancer.ts","../src/utils/lyric-split-words.ts","../src/utils/matrix.ts","../src/lyric-player/dom/lyric-line.ts","../src/lyric-player/dom/index.ts"],"sourcesContent":["import type { Disposable, HasElement } from \"../interfaces.ts\";\n\nexport abstract class AbstractBaseRenderer implements Disposable, HasElement {\n\t/**\n\t * 修改背景的流动速度,数字越大越快,默认为 8\n\t * @param speed 背景的流动速度,默认为 8\n\t */\n\tabstract setFlowSpeed(speed: number): void;\n\t/**\n\t * 修改背景的渲染比例,默认是 0.5\n\t *\n\t * 一般情况下这个程度既没有明显瑕疵也不会特别吃性能\n\t * @param scale 背景的渲染比例\n\t */\n\tabstract setRenderScale(scale: number): void;\n\t/**\n\t * 是否启用静态模式,即图片在更换后就会保持静止状态并禁用更新,以节省性能\n\t * @param enable 是否启用静态模式\n\t */\n\tabstract setStaticMode(enable: boolean): void;\n\t/**\n\t * 修改背景动画帧率,默认是 30 FPS\n\t *\n\t * 如果设置成 0 则会停止动画\n\t * @param fps 目标帧率,默认 30 FPS\n\t */\n\tabstract setFPS(fps: number): void;\n\t/**\n\t * 暂停背景动画,画面即便是更新了图片也不会发生变化\n\t */\n\tabstract pause(): void;\n\t/**\n\t * 恢复播放背景动画\n\t */\n\tabstract resume(): void;\n\t/**\n\t * 设置背景专辑资源,纹理加载并设置完成后会返回\n\t * @param albumSource 专辑的资源链接,可以是图片或视频链接,抑或是任意 img/video 元素,如果提供字符串链接且为视频则需要指定第二个参数\n\t */\n\tabstract setAlbum(\n\t\talbumSource: string | HTMLImageElement | HTMLVideoElement,\n\t\tisVideo?: boolean,\n\t): Promise<void>;\n\t/**\n\t * 设置低频的音量大小,范围在 80hz-120hz 之间为宜,取值范围在 [0.0-1.0] 之间\n\t *\n\t * 部分渲染器会根据音量大小调整背景效果(例如根据鼓点跳动)\n\t *\n\t * 如果无法获取到类似的数据,请传入 1.0 作为默认值,或不做任何处理(默认值即 1.0)\n\t * @param volume 低频的音量大小,范围在 50hz-120hz 之间为宜,取值范围在 [0.0-1.0] 之间\n\t */\n\tabstract setLowFreqVolume(volume: number): void;\n\t/**\n\t * 设置背景是否根据“是否有歌词”这个特征调整自身效果,例如有歌词时会变得更加活跃\n\t *\n\t * 部分渲染器会根据这个特征调整自身效果\n\t *\n\t * 如果不确定是否需要赋值或无法知晓是否包含歌词,请传入 true 或不做任何处理(默认值为 true)\n\t *\n\t * @param hasLyric 是否有歌词,如不确定是否需要赋值,请传入 true 或不做任何处理(默认值为 true)\n\t */\n\tabstract setHasLyric(hasLyric: boolean): void;\n\tabstract dispose(): void;\n\tabstract getElement(): HTMLElement;\n}\n\nfunction clamp1(x: number): number {\n\treturn Math.max(1, x);\n}\n\nexport abstract class BaseRenderer extends AbstractBaseRenderer {\n\tprivate observer: ResizeObserver;\n\tprotected flowSpeed = 1;\n\tprotected currerntRenderScale = 0.75;\n\tconstructor(protected canvas: HTMLCanvasElement) {\n\t\tsuper();\n\t\tthis.observer = new ResizeObserver(() => {\n\t\t\tconst width = clamp1(\n\t\t\t\tcanvas.clientWidth * window.devicePixelRatio * this.currerntRenderScale,\n\t\t\t);\n\t\t\tconst height = clamp1(\n\t\t\t\tcanvas.clientHeight *\n\t\t\t\t\twindow.devicePixelRatio *\n\t\t\t\t\tthis.currerntRenderScale,\n\t\t\t);\n\t\t\tthis.onResize(width, height);\n\t\t});\n\t\tthis.observer.observe(canvas);\n\t}\n\tsetRenderScale(scale: number): void {\n\t\tthis.currerntRenderScale = scale;\n\t\tthis.onResize(\n\t\t\tthis.canvas.clientWidth *\n\t\t\t\twindow.devicePixelRatio *\n\t\t\t\tthis.currerntRenderScale,\n\t\t\tthis.canvas.clientHeight *\n\t\t\t\twindow.devicePixelRatio *\n\t\t\t\tthis.currerntRenderScale,\n\t\t);\n\t}\n\t/**\n\t * 当画板元素大小发生变化时此函数会被调用\n\t * 可以在此处重设和渲染器相关的尺寸设置\n\t * 考虑到初始化的时候元素不一定在文档中或出于某些特殊样式状态,尺寸长宽有可能会为 0,请注意进行特判处理\n\t * @param width 画板元素实际的物理像素宽度,有可能为 0\n\t * @param height 画板元素实际的物理像素高度,有可能为 0\n\t */\n\tprotected onResize(width: number, height: number): void {\n\t\tthis.canvas.width = width;\n\t\tthis.canvas.height = height;\n\t}\n\t/**\n\t * 修改背景的流动速度,数字越大越快,默认为 1\n\t * @param speed 背景的流动速度,默认为 1\n\t */\n\tsetFlowSpeed(speed: number): void {\n\t\tthis.flowSpeed = speed;\n\t}\n\t/**\n\t * 是否启用静态模式,即图片在更换后就会保持静止状态并禁用更新,以节省性能\n\t * @param enable 是否启用静态模式\n\t */\n\tabstract override setStaticMode(enable: boolean): void;\n\t/**\n\t * 修改背景动画帧率,默认是 30 FPS\n\t *\n\t * 如果设置成 0 则会停止动画\n\t * @param fps 目标帧率,默认 30 FPS\n\t */\n\tabstract override setFPS(fps: number): void;\n\t/**\n\t * 暂停背景动画,画面即便是更新了图片也不会发生变化\n\t */\n\tabstract override pause(): void;\n\t/**\n\t * 恢复播放背景动画\n\t */\n\tabstract override resume(): void;\n\t/**\n\t * 设置背景专辑资源,纹理加载并设置完成后会返回\n\t * @param albumSource 专辑的资源链接,可以是图片或视频链接,抑或是任意 img/video 元素,如果提供字符串链接且为视频则需要指定第二个参数\n\t */\n\tabstract override setAlbum(\n\t\talbumSource: string | HTMLImageElement | HTMLVideoElement,\n\t\tisVideo?: boolean,\n\t): Promise<void>;\n\tdispose(): void {\n\t\tthis.observer.disconnect();\n\t\tthis.canvas.remove();\n\t}\n\toverride getElement(): HTMLElement {\n\t\treturn this.canvas;\n\t}\n}\n","export function loadImage(imageUrl: string): Promise<HTMLImageElement> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst img = document.createElement(\"img\");\n\t\timg.onload = () => resolve(img);\n\t\timg.onerror = reject;\n\t\timg.src = imageUrl;\n\t\timg.crossOrigin = \"anonymous\";\n\t\timg.loading = \"eager\";\n\t});\n}\n\nexport function loadVideo(videoUrl: string): Promise<HTMLVideoElement> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst video = document.createElement(\"video\");\n\t\tlet playing = false;\n\t\tlet timeupdate = false;\n\t\tlet rejected = false;\n\t\tvideo.addEventListener(\n\t\t\t\"playing\",\n\t\t\t() => {\n\t\t\t\tplaying = true;\n\t\t\t\tcheckReady();\n\t\t\t},\n\t\t\ttrue,\n\t\t);\n\t\tvideo.addEventListener(\n\t\t\t\"timeupdate\",\n\t\t\t() => {\n\t\t\t\ttimeupdate = true;\n\t\t\t\tcheckReady();\n\t\t\t},\n\t\t\ttrue,\n\t\t);\n\t\tvideo.addEventListener(\n\t\t\t\"error\",\n\t\t\t(err) => {\n\t\t\t\trejected = true;\n\t\t\t\treject(err);\n\t\t\t},\n\t\t\ttrue,\n\t\t);\n\t\tfunction checkReady() {\n\t\t\tif (playing && timeupdate && !rejected) {\n\t\t\t\tresolve(video);\n\t\t\t}\n\t\t}\n\t\tvideo.src = videoUrl;\n\t\tvideo.playsInline = true;\n\t\tvideo.crossOrigin = \"anonymous\";\n\t\tvideo.autoplay = true;\n\t\tvideo.loop = true;\n\t\tvideo.muted = true;\n\t\tvideo.play();\n\t});\n}\n\nexport function loadResourceFromUrl(\n\turl: string,\n\tisVideo = false,\n): Promise<HTMLImageElement | HTMLVideoElement> {\n\treturn isVideo ? loadVideo(url) : loadImage(url);\n}\n\nexport function loadResourceFromElement(\n\telement: HTMLImageElement | HTMLVideoElement,\n): Promise<HTMLImageElement | HTMLVideoElement> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (\n\t\t\telement instanceof HTMLImageElement\n\t\t\t\t? element.complete\n\t\t\t\t: element.readyState >= 3\n\t\t) {\n\t\t\tresolve(element);\n\t\t} else {\n\t\t\telement.onload = () => resolve(element);\n\t\t\telement.onerror = reject;\n\t\t}\n\t});\n}\n","export function blurImage(\n\timageData: ImageData,\n\tradius: number,\n\tquality: number,\n): void {\n\tconst pixels = imageData.data;\n\tconst width = imageData.width;\n\tconst height = imageData.height;\n\n\tlet rsum: number;\n\tlet gsum: number;\n\tlet bsum: number;\n\tlet asum: number;\n\tlet x: number;\n\tlet y: number;\n\tlet i: number;\n\tlet p: number;\n\tlet p1: number;\n\tlet p2: number;\n\tlet yp: number;\n\tlet yi: number;\n\tlet yw: number;\n\tconst wm = width - 1;\n\tconst hm = height - 1;\n\tconst rad1x = radius + 1;\n\tconst divx = radius + rad1x;\n\tconst rad1y = radius + 1;\n\tconst divy = radius + rad1y;\n\tconst div2 = 1 / (divx * divy);\n\n\tconst r: number[] = [];\n\tconst g: number[] = [];\n\tconst b: number[] = [];\n\tconst a: number[] = [];\n\n\tconst vmin: number[] = [];\n\tconst vmax: number[] = [];\n\n\twhile (quality-- > 0) {\n\t\tyw = yi = 0;\n\n\t\tfor (y = 0; y < height; y++) {\n\t\t\trsum = pixels[yw] * rad1x;\n\t\t\tgsum = pixels[yw + 1] * rad1x;\n\t\t\tbsum = pixels[yw + 2] * rad1x;\n\t\t\tasum = pixels[yw + 3] * rad1x;\n\n\t\t\tfor (i = 1; i <= radius; i++) {\n\t\t\t\tp = yw + ((i > wm ? wm : i) << 2);\n\t\t\t\trsum += pixels[p++];\n\t\t\t\tgsum += pixels[p++];\n\t\t\t\tbsum += pixels[p++];\n\t\t\t\tasum += pixels[p];\n\t\t\t}\n\n\t\t\tfor (x = 0; x < width; x++) {\n\t\t\t\tr[yi] = rsum;\n\t\t\t\tg[yi] = gsum;\n\t\t\t\tb[yi] = bsum;\n\t\t\t\ta[yi] = asum;\n\n\t\t\t\tif (y === 0) {\n\t\t\t\t\tvmin[x] = Math.min(x + rad1x, wm) << 2;\n\t\t\t\t\tvmax[x] = Math.max(x - radius, 0) << 2;\n\t\t\t\t}\n\n\t\t\t\tp1 = yw + vmin[x];\n\t\t\t\tp2 = yw + vmax[x];\n\n\t\t\t\trsum += pixels[p1++] - pixels[p2++];\n\t\t\t\tgsum += pixels[p1++] - pixels[p2++];\n\t\t\t\tbsum += pixels[p1++] - pixels[p2++];\n\t\t\t\tasum += pixels[p1] - pixels[p2];\n\n\t\t\t\tyi++;\n\t\t\t}\n\t\t\tyw += width << 2;\n\t\t}\n\n\t\tfor (x = 0; x < width; x++) {\n\t\t\typ = x;\n\t\t\trsum = r[yp] * rad1y;\n\t\t\tgsum = g[yp] * rad1y;\n\t\t\tbsum = b[yp] * rad1y;\n\t\t\tasum = a[yp] * rad1y;\n\n\t\t\tfor (i = 1; i <= radius; i++) {\n\t\t\t\typ += i > hm ? 0 : width;\n\t\t\t\trsum += r[yp];\n\t\t\t\tgsum += g[yp];\n\t\t\t\tbsum += b[yp];\n\t\t\t\tasum += a[yp];\n\t\t\t}\n\n\t\t\tyi = x << 2;\n\t\t\tfor (y = 0; y < height; y++) {\n\t\t\t\tpixels[yi] = (rsum * div2 + 0.5) | 0;\n\t\t\t\tpixels[yi + 1] = (gsum * div2 + 0.5) | 0;\n\t\t\t\tpixels[yi + 2] = (bsum * div2 + 0.5) | 0;\n\t\t\t\tpixels[yi + 3] = (asum * div2 + 0.5) | 0;\n\n\t\t\t\tif (x === 0) {\n\t\t\t\t\tvmin[y] = Math.min(y + rad1y, hm) * width;\n\t\t\t\t\tvmax[y] = Math.max(y - radius, 0) * width;\n\t\t\t\t}\n\n\t\t\t\tp1 = x + vmin[y];\n\t\t\t\tp2 = x + vmax[y];\n\n\t\t\t\trsum += r[p1] - r[p2];\n\t\t\t\tgsum += g[p1] - g[p2];\n\t\t\t\tbsum += b[p1] - b[p2];\n\t\t\t\tasum += a[p1] - a[p2];\n\n\t\t\t\tyi += width << 2;\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport function saturateImage(imageData: ImageData, saturation: number): void {\n\tconst pixels = imageData.data;\n\n\tfor (let i = 0; i < pixels.length; i += 4) {\n\t\tconst r = pixels[i];\n\t\tconst g = pixels[i + 1];\n\t\tconst b = pixels[i + 2];\n\t\tconst a = pixels[i + 3];\n\t\tconst gray = r * 0.3 + g * 0.59 + b * 0.11;\n\t\tpixels[i] = gray * (1 - saturation) + r * saturation;\n\t\tpixels[i + 1] = gray * (1 - saturation) + g * saturation;\n\t\tpixels[i + 2] = gray * (1 - saturation) + b * saturation;\n\t\tpixels[i + 3] = a;\n\t}\n}\n\nexport function brightnessImage(\n\timageData: ImageData,\n\tbrightness: number,\n): void {\n\tconst pixels = imageData.data;\n\n\tfor (let i = 0; i < pixels.length; i += 4) {\n\t\tconst r = pixels[i];\n\t\tconst g = pixels[i + 1];\n\t\tconst b = pixels[i + 2];\n\t\tconst a = pixels[i + 3];\n\t\tpixels[i] = r * brightness;\n\t\tpixels[i + 1] = g * brightness;\n\t\tpixels[i + 2] = b * brightness;\n\t\tpixels[i + 3] = a;\n\t}\n}\n\nexport function contrastImage(imageData: ImageData, contrast: number): void {\n\tconst pixels = imageData.data;\n\n\tfor (let i = 0; i < pixels.length; i += 4) {\n\t\tconst r = pixels[i];\n\t\tconst g = pixels[i + 1];\n\t\tconst b = pixels[i + 2];\n\t\tconst a = pixels[i + 3];\n\t\tpixels[i] = (r - 128) * contrast + 128;\n\t\tpixels[i + 1] = (g - 128) * contrast + 128;\n\t\tpixels[i + 2] = (b - 128) * contrast + 128;\n\t\tpixels[i + 3] = a;\n\t}\n}\n","export function clamp(x: number, min: number, max: number): number {\n\treturn Math.min(Math.max(x, min), max);\n}\n\nexport function clamp01(x: number): number {\n\treturn clamp(x, 0, 1);\n}\n\nexport function clampPositive(x: number): number {\n\treturn Math.max(0, x);\n}\n","/** @internal */\nexport interface ControlPointConf {\n\tcx: number;\n\tcy: number;\n\tx: number;\n\ty: number;\n\tur: number;\n\tvr: number;\n\tup: number;\n\tvp: number;\n}\n\n/** @internal */\nexport interface ControlPointPreset {\n\twidth: number;\n\theight: number;\n\tconf: ControlPointConf[];\n}\n\n/** @internal */\nexport const p = (\n\tcx: number,\n\tcy: number,\n\tx: number,\n\ty: number,\n\tur = 0,\n\tvr = 0,\n\tup = 1,\n\tvp = 1,\n) => Object.freeze({ cx, cy, x, y, ur, vr, up, vp }) as ControlPointConf;\n/** @internal */\nexport const preset = (\n\twidth: number,\n\theight: number,\n\tconf: ControlPointConf[],\n) => Object.freeze({ width, height, conf }) as ControlPointPreset;\n\nexport const CONTROL_POINT_PRESETS: ControlPointPreset[] = [\n\t// TODO: 竖屏推荐\n\tpreset(5, 5, [\n\t\tp(0, 0, -1, -1, 0, 0, 1, 1),\n\t\tp(1, 0, -0.5, -1, 0, 0, 1, 1),\n\t\tp(2, 0, 0, -1, 0, 0, 1, 1),\n\t\tp(3, 0, 0.5, -1, 0, 0, 1, 1),\n\t\tp(4, 0, 1, -1, 0, 0, 1, 1),\n\t\tp(0, 1, -1, -0.5, 0, 0, 1, 1),\n\t\tp(1, 1, -0.5, -0.5, 0, 0, 1, 1),\n\t\tp(2, 1, -0.0052029684413368305, -0.6131420587090777, 0, 0, 1, 1),\n\t\tp(3, 1, 0.5884227308309977, -0.3990805107556692, 0, 0, 1, 1),\n\t\tp(4, 1, 1, -0.5, 0, 0, 1, 1),\n\t\tp(0, 2, -1, 0, 0, 0, 1, 1),\n\t\tp(1, 2, -0.4210024670505933, -0.11895058380429502, 0, 0, 1, 1),\n\t\tp(2, 2, -0.1019613423315412, -0.023812118047224606, 0, -47, 0.629, 0.849),\n\t\tp(3, 2, 0.40275125660925437, -0.06345314544600389, 0, 0, 1, 1),\n\t\tp(4, 2, 1, 0, 0, 0, 1, 1),\n\t\tp(0, 3, -1, 0.5, 0, 0, 1, 1),\n\t\tp(1, 3, 0.06801958477287173, 0.5205913248960121, -31, -45, 1, 1),\n\t\tp(2, 3, 0.21446469120128908, 0.29331610114301043, 6, -56, 0.566, 1.321),\n\t\tp(3, 3, 0.5, 0.5, 0, 0, 1, 1),\n\t\tp(4, 3, 1, 0.5, 0, 0, 1, 1),\n\t\tp(0, 4, -1, 1, 0, 0, 1, 1),\n\t\tp(1, 4, -0.31378372841550195, 1, 0, 0, 1, 1),\n\t\tp(2, 4, 0.26153633255328046, 1, 0, 0, 1, 1),\n\t\tp(3, 4, 0.5, 1, 0, 0, 1, 1),\n\t\tp(4, 4, 1, 1, 0, 0, 1, 1),\n\t]),\n\t// TODO: 横屏推荐\n\tpreset(4, 4, [\n\t\tp(0, 0, -1, -1, 0, 0, 1, 1),\n\t\tp(1, 0, -0.33333333333333337, -1, 0, 0, 1, 1),\n\t\tp(2, 0, 0.33333333333333326, -1, 0, 0, 1, 1),\n\t\tp(3, 0, 1, -1, 0, 0, 1, 1),\n\t\tp(0, 1, -1, -0.04495399932657351, 0, 0, 1, 1),\n\t\tp(1, 1, -0.24056117520129328, -0.22465999020104, 0, 0, 1, 1),\n\t\tp(2, 1, 0.334758885767489, -0.00531297192779423, 0, 0, 1, 1),\n\t\tp(3, 1, 0.9989920470678106, -0.3382976020775408, 8, 0, 0.566, 1.792),\n\t\tp(0, 2, -1, 0.33333333333333326, 0, 0, 1, 1),\n\t\tp(1, 2, -0.3425497314639411, -0.000027501607956947893, 0, 0, 1, 1),\n\t\tp(2, 2, 0.3321437945812673, 0.1981776353859399, 0, 0, 1, 1),\n\t\tp(3, 2, 1, 0.0766118180296832, 0, 0, 1, 1),\n\t\tp(0, 3, -1, 1, 0, 0, 1, 1),\n\t\tp(1, 3, -0.33333333333333337, 1, 0, 0, 1, 1),\n\t\tp(2, 3, 0.33333333333333326, 1, 0, 0, 1, 1),\n\t\tp(3, 3, 1, 1, 0, 0, 1, 1),\n\t]),\n\tpreset(4, 4, [\n\t\tp(0, 0, -1, -1, 0, 0, 1, 2.075),\n\t\tp(1, 0, -0.33333333333333337, -1, 0, 0, 1, 1),\n\t\tp(2, 0, 0.33333333333333326, -1, 0, 0, 1, 1),\n\t\tp(3, 0, 1, -1, 0, 0, 1, 1),\n\t\tp(0, 1, -1, -0.4545779491139603, 0, 0, 1, 1),\n\t\tp(1, 1, -0.33333333333333337, -0.33333333333333337, 0, 0, 1, 1),\n\t\tp(2, 1, 0.0889403142626457, -0.6025711180694033, -32, 45, 1, 1),\n\t\tp(3, 1, 1, -0.33333333333333337, 0, 0, 1, 1),\n\t\tp(0, 2, -1, -0.07402408608567845, 1, 0, 1, 0.094),\n\t\tp(1, 2, -0.2719422694359541, 0.09775369930903222, 25, -18, 1.321, 0),\n\t\tp(2, 2, 0.19877414408395877, 0.4307383294587789, 48, -40, 0.755, 0.975),\n\t\tp(3, 2, 1, 0.33333333333333326, -37, 0, 1, 1),\n\t\tp(0, 3, -1, 1, 0, 0, 1, 1),\n\t\tp(1, 3, -0.33333333333333337, 1, 0, 0, 1, 1),\n\t\tp(2, 3, 0.5125850864305672, 1, -20, -18, 0, 1.604),\n\t\tp(3, 3, 1, 1, 0, 0, 1, 1),\n\t]),\n\tpreset(5, 5, [\n\t\tp(0, 0, -1, -1, 0, 0, 1, 1),\n\t\tp(1, 0, -0.4501953125, -1, 0, 55, 1, 2.075),\n\t\tp(2, 0, 0.1953125, -1, 0, 0, 1, 1),\n\t\tp(3, 0, 0.4580078125, -1, 0, -25, 1, 1),\n\t\tp(4, 0, 1, -1, 0, 0, 1, 1),\n\t\tp(0, 1, -1, -0.2514475377525607, -16, 0, 2.327, 0.943),\n\t\tp(1, 1, -0.55859375, -0.6609325945787148, 47, 0, 2.358, 0.377),\n\t\tp(2, 1, 0.232421875, -0.5244375756366635, -66, -25, 1.855, 1.164),\n\t\tp(3, 1, 0.685546875, -0.3753706470552125, 0, 0, 1, 1),\n\t\tp(4, 1, 1, -0.6699125300354287, 0, 0, 1, 1),\n\t\tp(0, 2, -1, 0.035910396862284255, 0, 0, 1, 1),\n\t\tp(1, 2, -0.4921875, 0.005378616309457018, 90, 23, 1, 1.981),\n\t\tp(2, 2, 0.021484375, -0.1365043639066228, 0, 42, 1, 1),\n\t\tp(3, 2, 0.4765625, 0.05925822904974043, -30, 0, 1.95, 0.44),\n\t\tp(4, 2, 1, 0.251428847823418, 0, 0, 1, 1),\n\t\tp(0, 3, -1, 0.6968336464764276, -68, 0, 1, 0.786),\n\t\tp(1, 3, -0.6904296875, 0.5890744209958608, -68, 0, 1, 1),\n\t\tp(2, 3, 0.1845703125, 0.3879238667654693, 61, 0, 1, 1),\n\t\tp(3, 3, 0.60546875, 0.4633553246018661, -47, -59, 0.849, 1.73),\n\t\tp(4, 3, 1, 0.6214021886400309, -33, 0, 0.377, 1.604),\n\t\tp(0, 4, -1, 1, 0, 0, 1, 1),\n\t\tp(1, 4, -0.5, 1, 0, -73, 1, 1),\n\t\tp(2, 4, -0.3271484375, 1, 0, -24, 0.314, 2.704),\n\t\tp(3, 4, 0.5, 1, 0, 0, 1, 1),\n\t\tp(4, 4, 1, 1, 0, 0, 1, 1),\n\t]),\n\tpreset(5, 5, [\n\t\tp(0, 0, -1, -1),\n\t\tp(1, 0, -0.6393, -1, 0, 0, 1, 2.3884),\n\t\tp(2, 0, 0, -1),\n\t\tp(3, 0, 0.5, -1),\n\t\tp(4, 0, 1, -1),\n\t\tp(0, 1, -1, -0.2301),\n\t\tp(1, 1, -0.6934, -0.331, 0, -0.7188, 1, 1.063),\n\t\tp(2, 1, -0.0082, -0.6814, -0.2583, 0, 1.0964, 1),\n\t\tp(3, 1, 0.5836, -0.531, 0.7029, 0, 1.5466, 1),\n\t\tp(4, 1, 1, -0.6407),\n\t\tp(0, 2, -1, 0.2973, 0, 0, 1.8352, 1),\n\t\tp(1, 2, -0.4082, 0.0602),\n\t\tp(2, 2, -0.1803, -0.3646, -0.2998, 0, 1.1513, 1),\n\t\tp(3, 2, 0.477, -0.1027, 0.8903, -0.1882, 1.0807, 0.8551),\n\t\tp(4, 2, 1, -0.2973),\n\t\tp(0, 3, -1, 0.7628, 0, 0, 2.3868, 1),\n\t\tp(1, 3, -0.2525, 0.4814, -0.8406, -1.6199, 1.4093, 1.2215),\n\t\tp(2, 3, 0.3607, 0.2814, -1.0713, -0.0529, 1.0025, 0.7611),\n\t\tp(3, 3, 0.4885, 0.623, 0, 0.8184, 1, 1.2876),\n\t\tp(4, 3, 1, 0.5),\n\t\tp(0, 4, -1, 1),\n\t\tp(1, 4, -0.4033, 1),\n\t\tp(2, 4, 0.2672, 1),\n\t\tp(3, 4, 0.5967, 1),\n\t\tp(4, 4, 1, 1),\n\t]),\n\tpreset(5, 5, [\n\t\tp(0, 0, -1, -1),\n\t\tp(1, 0, -0.2197, -1),\n\t\tp(2, 0, 0.0197, -1),\n\t\tp(3, 0, 0.8033, -1),\n\t\tp(4, 0, 1, -1),\n\t\tp(0, 1, -1, -0.5451),\n\t\tp(1, 1, -0.4885, -0.4035, -1.0246, -0.2268, 1.1936, 0.8005),\n\t\tp(2, 1, -0.1213, -0.2867, 0, -0.6981, 1, 0.809),\n\t\tp(3, 1, 0.3246, -0.5628, 0, -1.2188, 1, 1.044),\n\t\tp(4, 1, 1, -0.3292),\n\t\tp(0, 2, -1, 0.1416),\n\t\tp(1, 2, -0.341, -0.0142, 0, -0.4004, 1, 1.1293),\n\t\tp(2, 2, -0.0393, -0.023, 0.2915, -0.373, 1.044, 0.9879),\n\t\tp(3, 2, 0.3148, -0.0673, -0.7853, -0.8962, 1.4709, 1.0247),\n\t\tp(4, 2, 1, 0.1912),\n\t\tp(0, 3, -1, 0.5),\n\t\tp(1, 3, -0.2689, 0.2743, 0.3404, -0.5248, 1.0184, 0.4391),\n\t\tp(2, 3, 0.0721, 0.269, 0.5302, 0.1244, 0.6723, 0.3225),\n\t\tp(3, 3, 0.4148, 0.3894, -0.6977, -0.6783, 0.8094, 0.9247),\n\t\tp(4, 3, 1, 0.446),\n\t\tp(0, 4, -1, 1),\n\t\tp(1, 4, -0.7311, 1),\n\t\tp(2, 4, 0.323, 1),\n\t\tp(3, 4, 0.6393, 1),\n\t\tp(4, 4, 1, 1),\n\t]),\n] as const;\n","/**\n * @fileoverview\n * 实验性的随机控制点生成函数算法\n * 目的是取代原先大量的预设控制点代码\n */\n\nimport { clamp01 } from \"#utils/clamp.ts\";\nimport {\n\ttype ControlPointConf,\n\ttype ControlPointPreset,\n\tp,\n\tpreset,\n} from \"./cp-presets.ts\";\n\nconst randomRange = (min: number, max: number): number =>\n\tMath.random() * (max - min) + min;\n\nfunction smoothstep(edge0: number, edge1: number, x: number): number {\n\tconst t = clamp01((x - edge0) / (edge1 - edge0));\n\treturn t * t * (3 - 2 * t);\n}\n\nfunction smoothifyControlPoints(\n\tconf: ControlPointConf[],\n\tw: number,\n\th: number,\n\titerations = 2,\n\tfactor = 0.5,\n\tfactorIterationModifier = 0.1,\n): void {\n\tlet grid: ControlPointConf[][] = [];\n\tlet f = factor;\n\n\tfor (let j = 0; j < h; j++) {\n\t\tgrid[j] = [];\n\t\tfor (let i = 0; i < w; i++) {\n\t\t\tgrid[j][i] = conf[j * w + i];\n\t\t}\n\t}\n\n\tconst kernel = [\n\t\t[1, 2, 1],\n\t\t[2, 4, 2],\n\t\t[1, 2, 1],\n\t];\n\tconst kernelSum = 16;\n\n\tfor (let iter = 0; iter < iterations; iter++) {\n\t\tconst newGrid: ControlPointConf[][] = [];\n\t\tfor (let j = 0; j < h; j++) {\n\t\t\tnewGrid[j] = [];\n\t\t\tfor (let i = 0; i < w; i++) {\n\t\t\t\tif (i === 0 || i === w - 1 || j === 0 || j === h - 1) {\n\t\t\t\t\tnewGrid[j][i] = grid[j][i];\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlet sumX = 0;\n\t\t\t\tlet sumY = 0;\n\t\t\t\tlet sumUR = 0;\n\t\t\t\tlet sumVR = 0;\n\t\t\t\tlet sumUP = 0;\n\t\t\t\tlet sumVP = 0;\n\t\t\t\tfor (let dj = -1; dj <= 1; dj++) {\n\t\t\t\t\tfor (let di = -1; di <= 1; di++) {\n\t\t\t\t\t\tconst weight = kernel[dj + 1][di + 1];\n\t\t\t\t\t\tconst nb = grid[j + dj][i + di];\n\t\t\t\t\t\tsumX += nb.x * weight;\n\t\t\t\t\t\tsumY += nb.y * weight;\n\t\t\t\t\t\tsumUR += nb.ur * weight;\n\t\t\t\t\t\tsumVR += nb.vr * weight;\n\t\t\t\t\t\tsumUP += nb.up * weight;\n\t\t\t\t\t\tsumVP += nb.vp * weight;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst avgX = sumX / kernelSum;\n\t\t\t\tconst avgY = sumY / kernelSum;\n\t\t\t\tconst avgUR = sumUR / kernelSum;\n\t\t\t\tconst avgVR = sumVR / kernelSum;\n\t\t\t\tconst avgUP = sumUP / kernelSum;\n\t\t\t\tconst avgVP = sumVP / kernelSum;\n\n\t\t\t\tconst cur = grid[j][i];\n\t\t\t\tconst newX = cur.x * (1 - f) + avgX * f;\n\t\t\t\tconst newY = cur.y * (1 - f) + avgY * f;\n\t\t\t\tconst newUR = cur.ur * (1 - f) + avgUR * f;\n\t\t\t\tconst newVR = cur.vr * (1 - f) + avgVR * f;\n\t\t\t\tconst newUP = cur.up * (1 - f) + avgUP * f;\n\t\t\t\tconst newVP = cur.vp * (1 - f) + avgVP * f;\n\t\t\t\tnewGrid[j][i] = p(i, j, newX, newY, newUR, newVR, newUP, newVP);\n\t\t\t}\n\t\t}\n\t\tgrid = newGrid;\n\t\tf = clamp01(f + factorIterationModifier);\n\t}\n\n\tfor (let j = 0; j < h; j++) {\n\t\tfor (let i = 0; i < w; i++) {\n\t\t\tconf[j * w + i] = grid[j][i];\n\t\t}\n\t}\n}\n\nfunction noise(x: number, y: number): number {\n\treturn fract(Math.sin(x * 12.9898 + y * 78.233) * 43758.5453);\n}\n\nfunction fract(x: number): number {\n\treturn x - Math.floor(x);\n}\n\nfunction smoothNoise(x: number, y: number): number {\n\tconst x0 = Math.floor(x);\n\tconst y0 = Math.floor(y);\n\tconst x1 = x0 + 1;\n\tconst y1 = y0 + 1;\n\n\tconst xf = x - x0;\n\tconst yf = y - y0;\n\n\tconst u = xf * xf * (3 - 2 * xf);\n\tconst v = yf * yf * (3 - 2 * yf);\n\n\tconst n00 = noise(x0, y0);\n\tconst n10 = noise(x1, y0);\n\tconst n01 = noise(x0, y1);\n\tconst n11 = noise(x1, y1);\n\n\tconst nx0 = n00 * (1 - u) + n10 * u;\n\tconst nx1 = n01 * (1 - u) + n11 * u;\n\n\treturn nx0 * (1 - v) + nx1 * v;\n}\n\nfunction computeNoiseGradient(\n\tperlinFn: (x: number, y: number) => number,\n\tx: number,\n\ty: number,\n\tepsilon = 0.001,\n): [number, number] {\n\tconst n1 = perlinFn(x + epsilon, y);\n\tconst n2 = perlinFn(x - epsilon, y);\n\tconst n3 = perlinFn(x, y + epsilon);\n\tconst n4 = perlinFn(x, y - epsilon);\n\tconst dx = (n1 - n2) / (2 * epsilon);\n\tconst dy = (n3 - n4) / (2 * epsilon);\n\tconst len = Math.sqrt(dx * dx + dy * dy) || 1;\n\treturn [dx / len, dy / len];\n}\n\nexport function generateControlPoints(\n\twidth: number,\n\theight: number,\n\tvariationFraction: number = randomRange(0.4, 0.6), // = 0.2,\n\tnormalOffset: number = randomRange(0.3, 0.6), // = 0.3,\n\tblendFactor = 0.8,\n\tsmoothIters: number = Math.floor(randomRange(3, 5)), // = 3,\n\tsmoothFactor: number = randomRange(0.2, 0.3), // = 0.3,\n\tsmoothModifier: number = randomRange(-0.1, -0.05), // = -0.05,\n): ControlPointPreset {\n\tconst w = width ?? Math.floor(randomRange(3, 6));\n\tconst h = height ?? Math.floor(randomRange(3, 6));\n\n\tconst conf: ControlPointConf[] = [];\n\tconst dx = w === 1 ? 0 : 2 / (w - 1);\n\tconst dy = h === 1 ? 0 : 2 / (h - 1);\n\n\tfor (let j = 0; j < h; j++) {\n\t\tfor (let i = 0; i < w; i++) {\n\t\t\tconst baseX = (w === 1 ? 0 : i / (w - 1)) * 2 - 1;\n\t\t\tconst baseY = (h === 1 ? 0 : j / (h - 1)) * 2 - 1;\n\n\t\t\tconst isBorder = i === 0 || i === w - 1 || j === 0 || j === h - 1;\n\t\t\tconst pertX = isBorder\n\t\t\t\t? 0\n\t\t\t\t: randomRange(-variationFraction * dx, variationFraction * dx);\n\t\t\tconst pertY = isBorder\n\t\t\t\t? 0\n\t\t\t\t: randomRange(-variationFraction * dy, variationFraction * dy);\n\t\t\tlet x = baseX + pertX;\n\t\t\tlet y = baseY + pertY;\n\n\t\t\tconst ur = isBorder ? 0 : randomRange(-60, 60);\n\t\t\tconst vr = isBorder ? 0 : randomRange(-60, 60);\n\t\t\tconst up = isBorder ? 1 : randomRange(0.8, 1.2);\n\t\t\tconst vp = isBorder ? 1 : randomRange(0.8, 1.2);\n\n\t\t\tif (!isBorder) {\n\t\t\t\tconst uNorm = (baseX + 1) / 2;\n\t\t\t\tconst vNorm = (baseY + 1) / 2;\n\n\t\t\t\tconst [nx, ny] = computeNoiseGradient(smoothNoise, uNorm, vNorm, 0.001);\n\t\t\t\tlet offsetX = nx * normalOffset;\n\t\t\t\tlet offsetY = ny * normalOffset;\n\n\t\t\t\tconst distToBorder = Math.min(uNorm, 1 - uNorm, vNorm, 1 - vNorm); // in [0,0.5]\n\n\t\t\t\tconst weight = smoothstep(0, 1.0, distToBorder);\n\t\t\t\toffsetX *= weight;\n\t\t\t\toffsetY *= weight;\n\n\t\t\t\tx = x * (1 - blendFactor) + (x + offsetX) * blendFactor;\n\t\t\t\ty = y * (1 - blendFactor) + (y + offsetY) * blendFactor;\n\t\t\t}\n\t\t\tconf.push(p(i, j, x, y, ur, vr, up, vp));\n\t\t}\n\t}\n\n\tsmoothifyControlPoints(conf, w, h, smoothIters, smoothFactor, smoothModifier);\n\n\treturn preset(w, h, conf);\n}\n","/**\n * @fileoverview\n * 基于 Mesh Gradient 渐变渲染的渲染器\n * 此渲染应该是 Apple Music 使用的背景渲染方式了\n * 参考内容 https://movingparts.io/gradient-meshes\n */\n\nimport { Mat4, Vec2, Vec3, Vec4 } from \"gl-matrix\";\nimport type { Disposable } from \"../../interfaces.ts\";\nimport {\n\tloadResourceFromElement,\n\tloadResourceFromUrl,\n} from \"../../utils/resource.ts\";\nimport { BaseRenderer } from \"../base.ts\";\nimport { blurImage } from \"../img.ts\";\nimport { generateControlPoints } from \"./cp-generate.ts\";\nimport { CONTROL_POINT_PRESETS } from \"./cp-presets.ts\";\nimport meshFragShader from \"./mesh.frag.glsl?raw\";\nimport meshVertShader from \"./mesh.vert.glsl?raw\";\nimport { clamp01 } from \"#utils/clamp.ts\";\n\nconst quadVertShader = `\nattribute vec2 a_pos;\nvarying vec2 v_uv;\nvoid main() {\n gl_Position = vec4(a_pos, 0.0, 1.0);\n v_uv = a_pos * 0.5 + 0.5;\n}\n`;\n\nconst quadFragShader = `\nprecision mediump float;\nvarying vec2 v_uv;\nuniform sampler2D u_texture;\nuniform float u_alpha;\nvoid main() {\n vec4 color = texture2D(u_texture, v_uv);\n gl_FragColor = vec4(color.rgb, color.a * u_alpha);\n}\n`;\n\nfunction easeInOutSine(x: number): number {\n\treturn -(Math.cos(Math.PI * x) - 1) / 2;\n}\n\ntype RenderingContext = WebGLRenderingContext;\n\nclass GLProgram implements Disposable {\n\tprivate gl: RenderingContext;\n\tprogram: WebGLProgram;\n\tprivate vertexShader: WebGLShader;\n\tprivate fragmentShader: WebGLShader;\n\treadonly attrs: { [name: string]: number };\n\tconstructor(\n\t\tgl: RenderingContext,\n\t\tvertexShaderSource: string,\n\t\tfragmentShaderSource: string,\n\t\tprivate readonly label = \"unknown\",\n\t) {\n\t\tthis.gl = gl;\n\t\tthis.vertexShader = this.createShader(gl.VERTEX_SHADER, vertexShaderSource);\n\t\tthis.fragmentShader = this.createShader(\n\t\t\tgl.FRAGMENT_SHADER,\n\t\t\tfragmentShaderSource,\n\t\t);\n\t\tthis.program = this.createProgram();\n\n\t\tconst num = gl.getProgramParameter(this.program, gl.ACTIVE_ATTRIBUTES);\n\t\tconst attrs: { [name: string]: number } = {};\n\t\tfor (let i = 0; i < num; i++) {\n\t\t\tconst info = gl.getActiveAttrib(this.program, i);\n\t\t\tif (!info) continue;\n\t\t\tconst location = gl.getAttribLocation(this.program, info.name);\n\t\t\tif (location === -1) continue;\n\t\t\tattrs[info.name] = location;\n\t\t}\n\t\tthis.attrs = attrs;\n\t}\n\tprivate createShader(type: number, source: string) {\n\t\tconst gl = this.gl;\n\t\tconst shader = gl.createShader(type);\n\t\tif (!shader) throw new Error(\"Failed to create shader\");\n\t\tgl.shaderSource(shader, source);\n\t\tgl.compileShader(shader);\n\t\tif (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to compile shader for type ${type} \"${\n\t\t\t\t\tthis.label\n\t\t\t\t}\": ${gl.getShaderInfoLog(shader)}`,\n\t\t\t);\n\t\t}\n\t\treturn shader;\n\t}\n\tprivate createProgram() {\n\t\tconst gl = this.gl;\n\t\tconst program = gl.createProgram();\n\t\tif (!program) throw new Error(\"Failed to create program\");\n\t\tgl.attachShader(program, this.vertexShader);\n\t\tgl.attachShader(program, this.fragmentShader);\n\t\tgl.linkProgram(program);\n\t\tgl.validateProgram(program);\n\t\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\t\tconst errLog = gl.getProgramInfoLog(program);\n\t\t\tgl.deleteProgram(program);\n\t\t\tthrow new Error(`Failed to link program \"${this.label}\": ${errLog}`);\n\t\t}\n\t\treturn program;\n\t}\n\tuse() {\n\t\tconst gl = this.gl;\n\t\tgl.useProgram(this.program);\n\t}\n\tprivate notFoundUniforms: Set<string> = new Set();\n\tprivate warnUniformNotFound(name: string) {\n\t\tif (this.notFoundUniforms.has(name)) return;\n\t\tthis.notFoundUniforms.add(name);\n\t\tconsole.warn(\n\t\t\t`Failed to get uniform location for program \"${this.label}\": ${name}`,\n\t\t);\n\t}\n\tsetUniform1f(name: string, value: number) {\n\t\tconst gl = this.gl;\n\t\tconst location = gl.getUniformLocation(this.program, name);\n\t\tif (!location) this.warnUniformNotFound(name);\n\t\telse gl.uniform1f(location, value);\n\t}\n\tsetUniform2f(name: string, value1: number, value2: number) {\n\t\tconst gl = this.gl;\n\t\tconst location = gl.getUniformLocation(this.program, name);\n\t\tif (!location) this.warnUniformNotFound(name);\n\t\telse gl.uniform2f(location, value1, value2);\n\t}\n\tsetUniform1i(name: string, value: number) {\n\t\tconst gl = this.gl;\n\t\tconst location = gl.getUniformLocation(this.program, name);\n\t\tif (!location) this.warnUniformNotFound(name);\n\t\telse gl.uniform1i(location, value);\n\t}\n\tdispose() {\n\t\tconst gl = this.gl;\n\t\tgl.deleteShader(this.vertexShader);\n\t\tgl.deleteShader(this.fragmentShader);\n\t\tgl.deleteProgram(this.program);\n\t}\n}\n\nclass Mesh implements Disposable {\n\tprotected vertexWidth = 0;\n\tprotected vertexHeight = 0;\n\tprivate vertexBuffer: WebGLBuffer;\n\tprivate indexBuffer: WebGLBuffer;\n\tprivate vertexData: Float32Array;\n\tprivate indexData: Uint16Array;\n\tprivate vertexIndexLength = 0;\n\t// 调试用途,开启线框模式\n\tprivate wireFrame = false;\n\tconstructor(\n\t\tprivate readonly gl: RenderingContext,\n\t\tprivate readonly attrPos: number | undefined,\n\t\tprivate readonly attrColor: number | undefined,\n\t\tprivate readonly attrUV: number | undefined,\n\t) {\n\t\tconst vertexBuf = gl.createBuffer();\n\t\tif (!vertexBuf) throw new Error(\"Failed to create vertex buffer\");\n\t\tthis.vertexBuffer = vertexBuf;\n\t\tconst indexBuf = gl.createBuffer();\n\t\tif (!indexBuf) throw new Error(\"Failed to create index buffer\");\n\t\tthis.indexBuffer = indexBuf;\n\n\t\tthis.bind();\n\n\t\tthis.vertexData = new Float32Array(0);\n\t\tthis.indexData = new Uint16Array(0);\n\n\t\tthis.resize(2, 2);\n\t\tthis.update();\n\t}\n\n\tsetWireFrame(enable: boolean) {\n\t\tthis.wireFrame = enable;\n\t\tthis.resize(this.vertexWidth, this.vertexHeight);\n\t}\n\n\tsetVertexPos(vx: number, vy: number, x: number, y: number): void {\n\t\tconst idx = (vx + vy * this.vertexWidth) * 7;\n\t\tif (idx >= this.vertexData.length - 1) {\n\t\t\tconsole.warn(\"Vertex position out of range\", idx, this.vertexData.length);\n\t\t\treturn;\n\t\t}\n\t\tthis.vertexData[idx] = x;\n\t\tthis.vertexData[idx + 1] = y;\n\t}\n\n\tsetVertexColor(\n\t\tvx: number,\n\t\tvy: number,\n\t\tr: number,\n\t\tg: number,\n\t\tb: number,\n\t): void {\n\t\tconst idx = (vx + vy * this.vertexWidth) * 7 + 2;\n\t\tif (idx >= this.vertexData.length - 2) {\n\t\t\tconsole.warn(\"Vertex color out of range\", idx, this.vertexData.length);\n\t\t\treturn;\n\t\t}\n\t\tthis.vertexData[idx] = r;\n\t\tthis.vertexData[idx + 1] = g;\n\t\tthis.vertexData[idx + 2] = b;\n\t}\n\n\tsetVertexUV(vx: number, vy: number, x: number, y: number): void {\n\t\tconst idx = (vx + vy * this.vertexWidth) * 7 + 5;\n\t\tif (idx >= this.vertexData.length - 1) {\n\t\t\tconsole.warn(\"Vertex UV out of range\", idx, this.vertexData.length);\n\t\t\treturn;\n\t\t}\n\t\tthis.vertexData[idx] = x;\n\t\tthis.vertexData[idx + 1] = y;\n\t}\n\n\t// 批量设置顶点数据的优化方法\n\tsetVertexData(\n\t\tvx: number,\n\t\tvy: number,\n\t\tx: number,\n\t\ty: number,\n\t\tr: number,\n\t\tg: number,\n\t\tb: number,\n\t\tu: number,\n\t\tv: number,\n\t): void {\n\t\tconst idx = (vx + vy * this.vertexWidth) * 7;\n\t\tif (idx >= this.vertexData.length - 6) {\n\t\t\tconsole.warn(\"Vertex data out of range\", idx, this.vertexData.length);\n\t\t\treturn;\n\t\t}\n\t\tconst data = this.vertexData;\n\t\tdata[idx] = x;\n\t\tdata[idx + 1] = y;\n\t\tdata[idx + 2] = r;\n\t\tdata[idx + 3] = g;\n\t\tdata[idx + 4] = b;\n\t\tdata[idx + 5] = u;\n\t\tdata[idx + 6] = v;\n\t}\n\n\tgetVertexIndexLength(): number {\n\t\treturn this.vertexIndexLength;\n\t}\n\n\tdraw() {\n\t\tconst gl = this.gl;\n\n\t\tif (this.wireFrame) {\n\t\t\tgl.drawElements(gl.LINES, this.vertexIndexLength, gl.UNSIGNED_SHORT, 0);\n\t\t} else {\n\t\t\tgl.drawElements(\n\t\t\t\tgl.TRIANGLES,\n\t\t\t\tthis.vertexIndexLength,\n\t\t\t\tgl.UNSIGNED_SHORT,\n\t\t\t\t0,\n\t\t\t);\n\t\t}\n\t}\n\n\tresize(vertexWidth: number, vertexHeight: number): void {\n\t\tthis.vertexWidth = vertexWidth;\n\t\tthis.vertexHeight = vertexHeight;\n\t\t// 2 个顶点坐标 + 3 个颜色值 + 2 个 UV 坐标\n\t\tthis.vertexIndexLength = vertexWidth * vertexHeight * 6;\n\t\tif (this.wireFrame) {\n\t\t\tthis.vertexIndexLength = vertexWidth * vertexHeight * 10;\n\t\t}\n\t\tconst vertexData = new Float32Array(\n\t\t\tvertexWidth * vertexHeight * (2 + 3 + 2),\n\t\t);\n\t\tconst indexData = new Uint16Array(this.vertexIndexLength);\n\t\tthis.vertexData = vertexData;\n\t\tthis.indexData = indexData;\n\t\tfor (let y = 0; y < vertexHeight; y++) {\n\t\t\tfor (let x = 0; x < vertexWidth; x++) {\n\t\t\t\tconst px = (x / (vertexWidth - 1)) * 2 - 1;\n\t\t\t\tconst py = (y / (vertexHeight - 1)) * 2 - 1;\n\t\t\t\tthis.setVertexPos(x, y, px || 0, py || 0);\n\t\t\t\tthis.setVertexColor(x, y, 1, 1, 1);\n\t\t\t\tthis.setVertexUV(x, y, x / (vertexWidth - 1), y / (vertexHeight - 1));\n\t\t\t}\n\t\t}\n\t\tfor (let y = 0; y < vertexHeight - 1; y++) {\n\t\t\tfor (let x = 0; x < vertexWidth - 1; x++) {\n\t\t\t\tif (this.wireFrame) {\n\t\t\t\t\tconst idx = (y * vertexWidth + x) * 10;\n\n\t\t\t\t\tindexData[idx] = y * vertexWidth + x;\n\t\t\t\t\tindexData[idx + 1] = y * vertexWidth + x + 1;\n\n\t\t\t\t\tindexData[idx + 2] = y * vertexWidth + x + 1;\n\t\t\t\t\tindexData[idx + 3] = (y + 1) * vertexWidth + x;\n\n\t\t\t\t\tindexData[idx + 4] = (y + 1) * vertexWidth + x;\n\t\t\t\t\tindexData[idx + 5] = (y + 1) * vertexWidth + x + 1;\n\n\t\t\t\t\tindexData[idx + 6] = (y + 1) * vertexWidth + x + 1;\n\t\t\t\t\tindexData[idx + 7] = y * vertexWidth + x + 1;\n\n\t\t\t\t\tindexData[idx + 8] = y * vertexWidth + x;\n\t\t\t\t\tindexData[idx + 9] = (y + 1) * vertexWidth + x;\n\t\t\t\t} else {\n\t\t\t\t\tconst idx = (y * vertexWidth + x) * 6;\n\t\t\t\t\tindexData[idx] = y * vertexWidth + x;\n\t\t\t\t\tindexData[idx + 1] = y * vertexWidth + x + 1;\n\t\t\t\t\tindexData[idx + 2] = (y + 1) * vertexWidth + x;\n\t\t\t\t\tindexData[idx + 3] = y * vertexWidth + x + 1;\n\t\t\t\t\tindexData[idx + 4] = (y + 1) * vertexWidth + x + 1;\n\t\t\t\t\tindexData[idx + 5] = (y + 1) * vertexWidth + x;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst gl = this.gl;\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);\n\t\tgl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indexData, gl.STATIC_DRAW);\n\t}\n\n\tbind() {\n\t\tconst gl = this.gl;\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);\n\n\t\tif (this.attrPos !== undefined) {\n\t\t\tgl.vertexAttribPointer(this.attrPos, 2, gl.FLOAT, false, 4 * 7, 0);\n\t\t\tgl.enableVertexAttribArray(this.attrPos);\n\t\t}\n\t\tif (this.attrColor !== undefined) {\n\t\t\tgl.vertexAttribPointer(this.attrColor, 3, gl.FLOAT, false, 4 * 7, 4 * 2);\n\t\t\tgl.enableVertexAttribArray(this.attrColor);\n\t\t}\n\t\tif (this.attrUV !== undefined) {\n\t\t\tgl.vertexAttribPointer(this.attrUV, 2, gl.FLOAT, false, 4 * 7, 4 * 5);\n\t\t\tgl.enableVertexAttribArray(this.attrUV);\n\t\t}\n\t}\n\n\tupdate() {\n\t\tconst gl = this.gl;\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, this.vertexData, gl.DYNAMIC_DRAW);\n\t}\n\n\tdispose(): void {\n\t\tthis.gl.deleteBuffer(this.vertexBuffer);\n\t\tthis.gl.deleteBuffer(this.indexBuffer);\n\t}\n}\n\nclass ControlPoint {\n\tcolor: Vec3 = Vec3.fromValues(1, 1, 1);\n\tlocation: Vec2 = Vec2.fromValues(0, 0);\n\tuTangent: Vec2 = Vec2.fromValues(0, 0);\n\tvTangent: Vec2 = Vec2.fromValues(0, 0);\n\tprivate _uRot = 0;\n\tprivate _vRot = 0;\n\tprivate _uScale = 1;\n\tprivate _vScale = 1;\n\n\tconstructor() {\n\t\tObject.seal(this);\n\t}\n\n\tget uRot() {\n\t\treturn this._uRot;\n\t}\n\n\tget vRot() {\n\t\treturn this._vRot;\n\t}\n\n\tset uRot(value: number) {\n\t\tthis._uRot = value;\n\t\tthis.updateUTangent();\n\t}\n\n\tset vRot(value: number) {\n\t\tthis._vRot = value;\n\t\tthis.updateVTangent();\n\t}\n\n\tget uScale() {\n\t\treturn this._uScale;\n\t}\n\n\tget vScale() {\n\t\treturn this._vScale;\n\t}\n\n\tset uScale(value: number) {\n\t\tthis._uScale = value;\n\t\tthis.updateUTangent();\n\t}\n\n\tset vScale(value: number) {\n\t\tthis._vScale = value;\n\t\tthis.updateVTangent();\n\t}\n\n\tprivate updateUTangent() {\n\t\tthis.uTangent[0] = Math.cos(this._uRot) * this._uScale;\n\t\tthis.uTangent[1] = Math.sin(this._uRot) * this._uScale;\n\t}\n\n\tprivate updateVTangent() {\n\t\tthis.vTangent[0] = -Math.sin(this._vRot) * this._vScale;\n\t\tthis.vTangent[1] = Math.cos(this._vRot) * this._vScale;\n\t}\n}\n\nconst H = Mat4.fromValues(2, -2, 1, 1, -3, 3, -2, -1, 0, 0, 1, 0, 1, 0, 0, 0);\nconst H_T = Mat4.clone(H).transpose();\n\nfunction meshCoefficients(\n\tp00: ControlPoint,\n\tp01: ControlPoint,\n\tp10: ControlPoint,\n\tp11: ControlPoint,\n\taxis: \"x\" | \"y\",\n\toutput = Mat4.create(),\n): Mat4 {\n\tconst l = (p: ControlPoint) => p.location[axis];\n\tconst u = (p: ControlPoint) => p.uTangent[axis];\n\tconst v = (p: ControlPoint) => p.vTangent[axis];\n\n\toutput[0] = l(p00);\n\toutput[1] = l(p01);\n\toutput[2] = v(p00);\n\toutput[3] = v(p01);\n\toutput[4] = l(p10);\n\toutput[5] = l(p11);\n\toutput[6] = v(p10);\n\toutput[7] = v(p11);\n\toutput[8] = u(p00);\n\toutput[9] = u(p01);\n\toutput[10] = 0;\n\toutput[11] = 0;\n\toutput[12] = u(p10);\n\toutput[13] = u(p11);\n\toutput[14] = 0;\n\toutput[15] = 0;\n\n\treturn output;\n}\n\nfunction colorCoefficients(\n\tp00: ControlPoint,\n\tp01: ControlPoint,\n\tp10: ControlPoint,\n\tp11: ControlPoint,\n\taxis: \"r\" | \"g\" | \"b\",\n\toutput = Mat4.create(),\n): Mat4 {\n\tconst c = (p: ControlPoint) => p.color[axis];\n\toutput.fill(0);\n\toutput[0] = c(p00);\n\toutput[1] = c(p01);\n\toutput[4] = c(p10);\n\toutput[5] = c(p11);\n\t// return Mat4.fromValues(\n\t// c(p00), c(p01), 0, 0,\n\t// c(p10), c(p11), 0, 0,\n\t// 0, 0, 0, 0,\n\t// 0, 0, 0, 0,\n\t// );\n\treturn output;\n}\n\nclass Map2D<T> {\n\tprivate _width = 0;\n\tprivate _height = 0;\n\tprivate _data: T[] = [];\n\tconstructor(width: number, height: number) {\n\t\tthis.resize(width, height);\n\t\tObject.seal(this);\n\t}\n\tresize(width: number, height: number) {\n\t\tthis._width = width;\n\t\tthis._height = height;\n\t\tthis._data = new Array(width * height).fill(0);\n\t}\n\tset(x: number, y: number, value: T) {\n\t\tthis._data[x + y * this._width] = value;\n\t}\n\tget(x: number, y: number) {\n\t\treturn this._data[x + y * this._width];\n\t}\n\tget width() {\n\t\treturn this._width;\n\t}\n\tget height() {\n\t\treturn this._height;\n\t}\n}\n\n// Bicubic Hermite Patch Mesh\nclass BHPMesh extends Mesh {\n\t/**\n\t * 细分级别,越大曲线越平滑,但是性能消耗也越大\n\t */\n\tprivate _subDivisions = 10;\n\tprivate _controlPoints: Map2D<ControlPoint> = new Map2D(3, 3);\n\n\tconstructor(\n\t\tgl: RenderingContext,\n\t\tattrPos: number,\n\t\tattrColor: number,\n\t\tattrUV: number,\n\t) {\n\t\tsuper(gl, attrPos, attrColor, attrUV);\n\t\tthis.resizeControlPoints(3, 3);\n\t\tObject.seal(this);\n\t}\n\toverride setWireFrame(enable: boolean) {\n\t\tsuper.setWireFrame(enable);\n\t\tthis.updateMesh();\n\t}\n\t/**\n\t * 以当前的控制点矩阵大小和细分级别为参考重新设置细分级别,此操作不会重设控制点数据\n\t * @param subDivisions 细分级别\n\t */\n\tresetSubdivition(subDivisions: number) {\n\t\tthis._subDivisions = subDivisions;\n\t\tsuper.resize(\n\t\t\t(this._controlPoints.width - 1) * subDivisions,\n\t\t\t(this._controlPoints.height - 1) * subDivisions,\n\t\t);\n\t}\n\t/**\n\t * 重设控制点矩阵尺寸,将会重置所有控制点的颜色和坐标数据\n\t * 请在调用此方法后重新设置颜色和坐标,并调用 updateMesh 方法更新网格\n\t * @param width 控制点宽度数量,必须大于等于 2\n\t * @param height 控制点高度数量,必须大于等于 2\n\t */\n\tresizeControlPoints(width: number, height: number) {\n\t\tif (!(width >= 2 && height >= 2)) {\n\t\t\tthrow new Error(\"Control points must be larger than 3x3 or equal\");\n\t\t}\n\t\tthis._controlPoints.resize(width, height);\n\t\tfor (let y = 0; y < height; y++) {\n\t\t\tfor (let x = 0; x < width; x++) {\n\t\t\t\tconst point = new ControlPoint();\n\t\t\t\tpoint.location.x = (x / (width - 1)) * 2 - 1;\n\t\t\t\tpoint.location.y = (y / (height - 1)) * 2 - 1;\n\t\t\t\tpoint.uTangent.x = 2 / (width - 1);\n\t\t\t\tpoint.vTangent.y = 2 / (height - 1);\n\t\t\t\tthis._controlPoints.set(x, y, point);\n\t\t\t}\n\t\t}\n\t\tthis.resetSubdivition(this._subDivisions);\n\t}\n\t/**\n\t * 获取指定位置的控制点,然后可以设置颜色和坐标属性\n\t * 留意颜色属性和坐标属性的值范围均参考 WebGL 的定义\n\t * 即颜色各个组件取值 [0-1],坐标取值 [-1, 1]\n\t * 点的位置以画面左下角为原点 (0,0)\n\t * @param x 需要获取的控制点的 x 坐标\n\t * @param y 需要获取的控制点的 y 坐标\n\t * @returns 控制点对象\n\t */\n\tgetControlPoint(x: number, y: number) {\n\t\treturn this._controlPoints.get(x, y);\n\t}\n\t// 预分配重复使用的矩阵,避免频繁创建\n\tprivate tempX = Mat4.create();\n\tprivate tempY = Mat4.create();\n\tprivate tempR = Mat4.create();\n\tprivate tempG = Mat4.create();\n\tprivate tempB = Mat4.create();\n\n\tprivate tempXAcc = Mat4.create();\n\tprivate tempYAcc = Mat4.create();\n\tprivate tempRAcc = Mat4.create();\n\tprivate tempGAcc = Mat4.create();\n\tprivate tempBAcc = Mat4.create();\n\n\tprivate tempUx = Vec4.create();\n\tprivate tempUy = Vec4.create();\n\tprivate tempUr = Vec4.create();\n\tprivate tempUg = Vec4.create();\n\tprivate tempUb = Vec4.create();\n\n\tprivate precomputeMatrix(M: Mat4, output: Mat4) {\n\t\toutput.copy(M).transpose();\n\t\tMat4.mul(output, output, H);\n\t\tMat4.mul(output, H_T, output);\n\t\treturn output;\n\t}\n\n\t/**\n\t * 更新最终呈现的网格数据,此方法应在所有控制点或细分参数的操作完成后调用\n\t */\n\tupdateMesh() {\n\t\tconst subDivM1 = this._subDivisions - 1;\n\t\tconst tW = subDivM1 * (this._controlPoints.height - 1);\n\t\tconst tH = subDivM1 * (this._controlPoints.width - 1);\n\t\tconst controlPointsWidth = this._controlPoints.width;\n\t\tconst controlPointsHeight = this._controlPoints.height;\n\t\tconst subDivisions = this._subDivisions;\n\n\t\t// 预计算常用值\n\t\tconst invSubDivM1 = 1 / subDivM1;\n\t\tconst invTH = 1 / tH;\n\t\tconst invTW = 1 / tW;\n\n\t\t// 预计算 u 和 v 的幂次\n\t\tconst normPowers = new Float32Array(subDivisions * 4);\n\t\tfor (let i = 0; i < subDivisions; i++) {\n\t\t\tconst norm = i * invSubDivM1;\n\t\t\tconst idx = i * 4;\n\t\t\tnormPowers[idx] = norm ** 3;\n\t\t\tnormPowers[idx + 1] = norm ** 2;\n\t\t\tnormPowers[idx + 2] = norm;\n\t\t\tnormPowers[idx + 3] = 1;\n\t\t}\n\n\t\tfor (let x = 0; x < controlPointsWidth - 1; x++) {\n\t\t\tfor (let y = 0; y < controlPointsHeight - 1; y++) {\n\t\t\t\tconst p00 = this._controlPoints.get(x, y);\n\t\t\t\tconst p01 = this._controlPoints.get(x, y + 1);\n\t\t\t\tconst p10 = this._controlPoints.get(x + 1, y);\n\t\t\t\tconst p11 = this._controlPoints.get(x + 1, y + 1);\n\n\t\t\t\t// 复用预分配的矩阵\n\t\t\t\tmeshCoefficients(p00, p01, p10, p11, \"x\", this.tempX);\n\t\t\t\tmeshCoefficients(p00, p01, p10, p11, \"y\", this.tempY);\n\t\t\t\tcolorCoefficients(p00, p01, p10, p11, \"r\", this.tempR);\n\t\t\t\tcolorCoefficients(p00, p01, p10, p11, \"g\", this.tempG);\n\t\t\t\tcolorCoefficients(p00, p01, p10, p11, \"b\", this.tempB);\n\n\t\t\t\t// 预计算累加矩阵\n\t\t\t\tthis.precomputeMatrix(this.tempX, this.tempXAcc);\n\t\t\t\tthis.precomputeMatrix(this.tempY, this.tempYAcc);\n\t\t\t\tthis.precomputeMatrix(this.tempR, this.tempRAcc);\n\t\t\t\tthis.precomputeMatrix(this.tempG, this.tempGAcc);\n\t\t\t\tthis.precomputeMatrix(this.tempB, this.tempBAcc);\n\n\t\t\t\tconst sX = x / (controlPointsWidth - 1);\n\t\t\t\tconst sY = y / (controlPointsHeight - 1);\n\t\t\t\tconst baseVx = y * subDivisions;\n\t\t\t\tconst baseVy = x * subDivisions;\n\n\t\t\t\tfor (let u = 0; u < subDivisions; u++) {\n\t\t\t\t\tconst vxOffset = baseVx + u;\n\t\t\t\t\tconst uIdx = u * 4;\n\n\t\t\t\t\tthis.tempUx[0] = normPowers[uIdx];\n\t\t\t\t\tthis.tempUx[1] = normPowers[uIdx + 1];\n\t\t\t\t\tthis.tempUx[2] = normPowers[uIdx + 2];\n\t\t\t\t\tthis.tempUx[3] = normPowers[uIdx + 3];\n\t\t\t\t\tVec4.transformMat4(this.tempUx, this.tempUx, this.tempXAcc);\n\n\t\t\t\t\tthis.tempUy[0] = normPowers[uIdx];\n\t\t\t\t\tthis.tempUy[1] = normPowers[uIdx + 1];\n\t\t\t\t\tthis.tempUy[2] = normPowers[uIdx + 2];\n\t\t\t\t\tthis.tempUy[3] = normPowers[uIdx + 3];\n\t\t\t\t\tVec4.transformMat4(this.tempUy, this.tempUy, this.tempYAcc);\n\n\t\t\t\t\tthis.tempUr[0] = normPowers[uIdx];\n\t\t\t\t\tthis.tempUr[1] = normPowers[uIdx + 1];\n\t\t\t\t\tthis.tempUr[2] = normPowers[uIdx + 2];\n\t\t\t\t\tthis.tempUr[3] = normPowers[uIdx + 3];\n\t\t\t\t\tVec4.transformMat4(this.tempUr, this.tempUr, this.tempRAcc);\n\n\t\t\t\t\tthis.tempUg[0] = normPowers[uIdx];\n\t\t\t\t\tthis.tempUg[1] = normPowers[uIdx + 1];\n\t\t\t\t\tthis.tempUg[2] = normPowers[uIdx + 2];\n\t\t\t\t\tthis.tempUg[3] = normPowers[uIdx + 3];\n\t\t\t\t\tVec4.transformMat4(this.tempUg, this.tempUg, this.tempGAcc);\n\n\t\t\t\t\tthis.tempUb[0] = normPowers[uIdx];\n\t\t\t\t\tthis.tempUb[1] = normPowers[uIdx + 1];\n\t\t\t\t\tthis.tempUb[2] = normPowers[uIdx + 2];\n\t\t\t\t\tthis.tempUb[3] = normPowers[uIdx + 3];\n\t\t\t\t\tVec4.transformMat4(this.tempUb, this.tempUb, this.tempBAcc);\n\n\t\t\t\t\tfor (let v = 0; v < subDivisions; v++) {\n\t\t\t\t\t\tconst vy = baseVy + v;\n\t\t\t\t\t\tconst vIdx = v * 4;\n\n\t\t\t\t\t\tconst v0 = normPowers[vIdx];\n\t\t\t\t\t\tconst v1 = normPowers[vIdx + 1];\n\t\t\t\t\t\tconst v2 = normPowers[vIdx + 2];\n\t\t\t\t\t\tconst v3 = normPowers[vIdx + 3];\n\n\t\t\t\t\t\tconst px =\n\t\t\t\t\t\t\tv0 * this.tempUx[0] +\n\t\t\t\t\t\t\tv1 * this.tempUx[1] +\n\t\t\t\t\t\t\tv2 * this.tempUx[2] +\n\t\t\t\t\t\t\tv3 * this.tempUx[3];\n\t\t\t\t\t\tconst py =\n\t\t\t\t\t\t\tv0 * this.tempUy[0] +\n\t\t\t\t\t\t\tv1 * this.tempUy[1] +\n\t\t\t\t\t\t\tv2 * this.tempUy[2] +\n\t\t\t\t\t\t\tv3 * this.tempUy[3];\n\t\t\t\t\t\tconst pr =\n\t\t\t\t\t\t\tv0 * this.tempUr[0] +\n\t\t\t\t\t\t\tv1 * this.tempUr[1] +\n\t\t\t\t\t\t\tv2 * this.tempUr[2] +\n\t\t\t\t\t\t\tv3 * this.tempUr[3];\n\t\t\t\t\t\tconst pg =\n\t\t\t\t\t\t\tv0 * this.tempUg[0] +\n\t\t\t\t\t\t\tv1 * this.tempUg[1] +\n\t\t\t\t\t\t\tv2 * this.tempUg[2] +\n\t\t\t\t\t\t\tv3 * this.tempUg[3];\n\t\t\t\t\t\tconst pb =\n\t\t\t\t\t\t\tv0 * this.tempUb[0] +\n\t\t\t\t\t\t\tv1 * this.tempUb[1] +\n\t\t\t\t\t\t\tv2 * this.tempUb[2] +\n\t\t\t\t\t\t\tv3 * this.tempUb[3];\n\n\t\t\t\t\t\tconst uvX = sX + v * invTH;\n\t\t\t\t\t\tconst uvY = 1 - sY - u * invTW;\n\n\t\t\t\t\t\t// 使用批量设置方法减少数组访问次数\n\t\t\t\t\t\tthis.setVertexData(vxOffset, vy, px, py, pr, pg, pb, uvX, uvY);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.update();\n\t}\n}\n\nclass GLTexture implements Disposable {\n\treadonly tex: WebGLTexture;\n\n\tconstructor(\n\t\tprivate gl: WebGLRenderingContext,\n\t\talbumImageData: ImageData,\n\t) {\n\t\tconst albumTexture = gl.createTexture();\n\t\tif (!albumTexture) throw new Error(\"Failed to create texture\");\n\t\tthis.tex = albumTexture;\n\t\tgl.activeTexture(gl.TEXTURE0);\n\t\tgl.bindTexture(gl.TEXTURE_2D, albumTexture);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\talbumImageData,\n\t\t);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);\n\t}\n\n\tbind() {\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, this.tex);\n\t}\n\n\tdispose(): void {\n\t\tthis.gl.deleteTexture(this.tex);\n\t}\n}\n\nfunction createOffscreenCanvas(width: number, height: number) {\n\tif (\"OffscreenCanvas\" in window) return new OffscreenCanvas(width, height);\n\tconst canvas = document.createElement(\"canvas\");\n\tcanvas.width = width;\n\tcanvas.height = height;\n\treturn canvas;\n}\n\ninterface MeshState {\n\tmesh: BHPMesh;\n\ttexture: GLTexture;\n\talpha: number;\n}\n\nexport class MeshGradientRenderer extends BaseRenderer {\n\tprivate gl: RenderingContext;\n\tprivate lastFrameTime = 0;\n\tprivate frameTime = 0;\n\t// private currentImageData?: ImageData;\n\tprivate lastTickTime = 0;\n\tprivate smoothedVolume = 0;\n\tprivate volume = 0;\n\tprivate tickHandle = 0;\n\tprivate maxFPS = 60;\n\tprivate paused = false;\n\tprivate staticMode = false;\n\tprivate mainProgram: GLProgram;\n\tprivate quadProgram: GLProgram;\n\tprivate quadBuffer: WebGLBuffer;\n\tprivate fbo: WebGLFramebuffer | null = null;\n\tprivate fboTexture: WebGLTexture | null = null;\n\tprivate manualControl = false;\n\tprivate reduceImageSizeCanvas = createOffscreenCanvas(\n\t\t32,\n\t\t32,\n\t) as HTMLCanvasElement;\n\tprivate targetSize = Vec2.fromValues(0, 0);\n\tprivate currentSize = Vec2.fromValues(0, 0);\n\tprivate isNoCover = true;\n\tprivate meshStates: MeshState[] = [];\n\tprivate _disposed = false;\n\t// 性能监控\n\tprivate frameCount = 0;\n\tprivate lastFPSUpdate = 0;\n\tprivate currentFPS = 0;\n\tprivate enablePerformanceMonitoring = false;\n\n\tsetManualControl(enable: boolean): void {\n\t\tthis.manualControl = enable;\n\t}\n\n\tsetWireFrame(enable: boolean): void {\n\t\tfor (const state of this.meshStates) {\n\t\t\tstate.mesh.setWireFrame(enable);\n\t\t}\n\t}\n\n\tgetControlPoint(x: number, y: number): ControlPoint | undefined {\n\t\treturn this.meshStates[this.meshStates.length - 1]?.mesh?.getControlPoint(\n\t\t\tx,\n\t\t\ty,\n\t\t);\n\t}\n\n\tresizeControlPoints(width: number, height: number): void {\n\t\tthis.meshStates[this.meshStates.length - 1]?.mesh?.resizeControlPoints(\n\t\t\twidth,\n\t\t\theight,\n\t\t);\n\t}\n\n\tresetSubdivition(subDivisions: number): void {\n\t\tthis.meshStates[this.meshStates.length - 1]?.mesh?.resetSubdivition(\n\t\t\tsubDivisions,\n\t\t);\n\t}\n\n\tprivate onTick(tickTime: number) {\n\t\tthis.tickHandle = 0;\n\t\tif (this.paused) return;\n\t\tif (this._disposed) return;\n\n\t\t// 更新性能统计\n\t\tthis.updatePerformanceStats(tickTime);\n\n\t\tconst interval = 1000 / this.maxFPS;\n\t\tconst delta = tickTime - this.lastTickTime;\n\t\tif (delta < interval) {\n\t\t\tthis.requestTick();\n\t\t\treturn;\n\t\t}\n\n\t\tif (Number.isNaN(this.lastFrameTime)) {\n\t\t\tthis.lastFrameTime = tickTime;\n\t\t}\n\t\tconst frameDelta = tickTime - this.lastFrameTime;\n\t\tthis.lastFrameTime = tickTime;\n\t\t// 减去多余的时间,避免帧率漂移(例如高刷显示器限制低帧率时)\n\t\tthis.lastTickTime = tickTime - (delta % interval);\n\n\t\tthis.frameTime += frameDelta * this.flowSpeed;\n\n\t\tif (!(this.onRedraw(this.frameTime, frameDelta) && this.staticMode)) {\n\t\t\tthis.requestTick();\n\t\t} else if (this.staticMode) {\n\t\t\tthis.lastFrameTime = Number.NaN;\n\t\t}\n\t}\n\n\tprivate checkIfResize() {\n\t\tconst [tW, tH] = [this.targetSize.x, this.targetSize.y];\n\t\tconst [cW, cH] = [this.currentSize.x, this.currentSize.y];\n\t\tif (tW !== cW || tH !== cH) {\n\t\t\tsuper.onResize(tW, tH);\n\t\t\tconst gl = this.gl;\n\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\t\tgl.viewport(0, 0, tW, tH);\n\t\t\tthis.currentSize.x = tW;\n\t\t\tthis.currentSize.y = tH;\n\t\t\tif (tW > 0 && tH > 0) {\n\t\t\t\tthis.updateFBO(tW, tH);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate updateFBO(width: number, height: number) {\n\t\tconst gl = this.gl;\n\t\tif (this.fbo) gl.deleteFramebuffer(this.fbo);\n\t\tif (this.fboTexture) gl.deleteTexture(this.fboTexture);\n\n\t\tthis.fboTexture = gl.createTexture();\n\t\tgl.bindTexture(gl.TEXTURE_2D, this.fboTexture);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\twidth,\n\t\t\theight,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\tnull,\n\t\t);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n\t\tthis.fbo = gl.createFramebuffer();\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);\n\t\tgl.framebufferTexture2D(\n\t\t\tgl.FRAMEBUFFER,\n\t\t\tgl.COLOR_ATTACHMENT0,\n\t\t\tgl.TEXTURE_2D,\n\t\t\tthis.fboTexture,\n\t\t\t0,\n\t\t);\n\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t}\n\n\tprivate onRedraw(tickTime: number, delta: number) {\n\t\tconst latestMeshState = this.meshStates[this.meshStates.length - 1];\n\t\tlet canBeStatic = false;\n\n\t\t// 预计算常用值\n\t\tconst deltaFactor = delta / 500;\n\n\t\tif (latestMeshState) {\n\t\t\tlatestMeshState.mesh.bind();\n\t\t\t// 考虑到我们并不逐帧更新网格控制点,因此也不需要重复调用 updateMesh\n\t\t\tif (this.manualControl) latestMeshState.mesh.updateMesh();\n\n\t\t\tif (this.isNoCover) {\n\t\t\t\t// 批量处理alpha更新,减少循环开销\n\t\t\t\tlet hasActiveStates = false;\n\t\t\t\tfor (let i = this.meshStates.length - 1; i >= 0; i--) {\n\t\t\t\t\tconst state = this.meshStates[i];\n\t\t\t\t\t// 增加一个小的容错范围,避免浮点误差导致的过早删除\n\t\t\t\t\tif (state.alpha <= -0.1) {\n\t\t\t\t\t\t// 立即释放资源\n\t\t\t\t\t\tstate.mesh.dispose();\n\t\t\t\t\t\tstate.texture.dispose();\n\t\t\t\t\t\tthis.meshStates.splice(i, 1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstate.alpha = Math.max(-0.1, state.alpha - deltaFactor);\n\t\t\t\t\t\thasActiveStates = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcanBeStatic = !hasActiveStates;\n\t\t\t} else {\n\t\t\t\t// 同样增加容错范围,允许稍微超过1以确保完全过渡完成\n\t\t\t\tif (latestMeshState.alpha >= 1.1) {\n\t\t\t\t\t// 批量清理旧状态\n\t\t\t\t\tconst deleted = this.meshStates.splice(0, this.meshStates.length - 1);\n\t\t\t\t\tfor (const state of deleted) {\n\t\t\t\t\t\tstate.mesh.dispose();\n\t\t\t\t\t\tstate.texture.dispose();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlatestMeshState.alpha = Math.min(\n\t\t\t\t\t\t1.1,\n\t\t\t\t\t\tlatestMeshState.alpha + deltaFactor,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcanBeStatic =\n\t\t\t\t\tthis.meshStates.length === 1 && latestMeshState.alpha >= 1.1;\n\t\t\t}\n\t\t}\n\n\t\tconst gl = this.gl;\n\t\tthis.checkIfResize();\n\n\t\tif (!this.fbo) return canBeStatic;\n\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\tgl.clearColor(0, 0, 0, 0);\n\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\n\t\tconst lerpFactor = Math.min(1.0, delta / 100.0);\n\t\tthis.smoothedVolume += (this.volume - this.smoothedVolume) * lerpFactor;\n\n\t\t// 渲染所有网格状态\n\t\tfor (const state of this.meshStates) {\n\t\t\t// 1. 渲染到 FBO\n\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);\n\t\t\tgl.disable(gl.BLEND);\n\t\t\tgl.clearColor(0, 0, 0, 0);\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\n\t\t\tthis.mainProgram.use();\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tthis.mainProgram.setUniform1f(\"u_time\", tickTime / 10000);\n\t\t\tthis.mainProgram.setUniform1f(\n\t\t\t\t\"u_aspect\",\n\t\t\t\tthis.manualControl ? 1 : this.canvas.width / this.canvas.height,\n\t\t\t);\n\t\t\tthis.mainProgram.setUniform1i(\"u_texture\", 0);\n\t\t\tthis.mainProgram.setUniform1f(\"u_volume\", this.volume);\n\t\t\tthis.mainProgram.setUniform1f(\"u_alpha\", 1.0);\n\n\t\t\tstate.texture.bind();\n\t\t\tstate.mesh.bind();\n\t\t\tstate.mesh.draw();\n\n\t\t\t// 2. 渲染 FBO 到屏幕\n\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\t\tgl.enable(gl.BLEND);\n\t\t\tgl.blendFuncSeparate(\n\t\t\t\tgl.SRC_ALPHA,\n\t\t\t\tgl.ONE_MINUS_SRC_ALPHA,\n\t\t\t\tgl.ONE,\n\t\t\t\tgl.ONE_MINUS_SRC_ALPHA,\n\t\t\t);\n\t\t\tthis.quadProgram.use();\n\t\t\tthis.quadProgram.setUniform1i(\"u_texture\", 0);\n\t\t\tthis.quadProgram.setUniform1f(\n\t\t\t\t\"u_alpha\",\n\t\t\t\teaseInOutSine(clamp01(state.alpha)),\n\t\t\t);\n\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, this.fboTexture);\n\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n\t\t\tconst a_pos = this.quadProgram.attrs.a_pos;\n\t\t\tgl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0);\n\t\t\tgl.enableVertexAttribArray(a_pos);\n\n\t\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\t\t\tgl.disableVertexAttribArray(a_pos);\n\t\t}\n\n\t\tgl.flush();\n\n\t\treturn canBeStatic;\n\t}\n\n\tprivate onTickBinded = this.onTick.bind(this);\n\n\tprivate requestTick() {\n\t\tif (this._disposed) return;\n\t\tif (this.tickHandle === 0)\n\t\t\tthis.tickHandle = requestAnimationFrame(this.onTickBinded);\n\t}\n\n\t// private supportTextureFloat = true;\n\n\tconstructor(canvas: HTMLCanvasElement) {\n\t\tsuper(canvas);\n\n\t\tconst gl = canvas.getContext(\"webgl\", { antialias: true });\n\t\tif (!gl) throw new Error(\"WebGL not supported\");\n\t\tif (!gl.getExtension(\"EXT_color_buffer_float\"))\n\t\t\tconsole.warn(\"EXT_color_buffer_float not supported\");\n\t\tif (!gl.getExtension(\"EXT_float_blend\")) {\n\t\t\tconsole.warn(\"EXT_float_blend not supported\");\n\t\t\t// this.supportTextureFloat = false;\n\t\t}\n\t\tif (!gl.getExtension(\"OES_texture_float_linear\"))\n\t\t\tconsole.warn(\"OES_texture_float_linear not supported\");\n\t\tif (!gl.getExtension(\"OES_texture_float\")) {\n\t\t\t// this.supportTextureFloat = false;\n\t\t\tconsole.warn(\"OES_texture_float not supported\");\n\t\t}\n\n\t\tthis.gl = gl;\n\t\tgl.enable(gl.BLEND);\n\t\tgl.blendFuncSeparate(\n\t\t\tgl.SRC_ALPHA,\n\t\t\tgl.ONE_MINUS_SRC_ALPHA,\n\t\t\tgl.ONE,\n\t\t\tgl.ONE_MINUS_SRC_ALPHA,\n\t\t);\n\t\tgl.enable(gl.DEPTH_TEST);\n\t\tgl.depthFunc(gl.ALWAYS);\n\n\t\tthis.mainProgram = new GLProgram(\n\t\t\tgl,\n\t\t\tmeshVertShader,\n\t\t\tmeshFragShader,\n\t\t\t\"main-program-mg\",\n\t\t);\n\n\t\tthis.quadProgram = new GLProgram(\n\t\t\tgl,\n\t\t\tquadVertShader,\n\t\t\tquadFragShader,\n\t\t\t\"quad-program\",\n\t\t);\n\t\tconst quadBuffer = gl.createBuffer();\n\t\tif (!quadBuffer) throw new Error(\"Failed to create quad buffer\");\n\t\tthis.quadBuffer = quadBuffer;\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n\t\tgl.bufferData(\n\t\t\tgl.ARRAY_BUFFER,\n\t\t\tnew Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]),\n\t\t\tgl.STATIC_DRAW,\n\t\t);\n\n\t\tthis.requestTick();\n\t}\n\n\tprotected override onResize(width: number, height: number): void {\n\t\tthis.targetSize.x = Math.ceil(width);\n\t\tthis.targetSize.y = Math.ceil(height);\n\t\tthis.requestTick();\n\t}\n\n\toverride setStaticMode(enable: boolean): void {\n\t\tthis.staticMode = enable;\n\t\tthis.lastFrameTime = performance.now();\n\t\tthis.requestTick();\n\t}\n\toverride setFPS(fps: number): void {\n\t\tthis.maxFPS = fps;\n\t}\n\toverride pause(): void {\n\t\tif (this.tickHandle) {\n\t\t\tcancelAnimationFrame(this.tickHandle);\n\t\t\tthis.tickHandle = 0;\n\t\t}\n\t\tthis.paused = true;\n\t}\n\toverride resume(): void {\n\t\tthis.paused = false;\n\t\tthis.requestTick();\n\t}\n\toverride async setAlbum(\n\t\talbumSource?: string | HTMLImageElement | HTMLVideoElement,\n\t\tisVideo?: boolean,\n\t): Promise<void> {\n\t\tif (\n\t\t\talbumSource === undefined ||\n\t\t\t(typeof albumSource === \"string\" && albumSource.trim().length === 0)\n\t\t) {\n\t\t\tthis.isNoCover = true;\n\t\t\treturn;\n\t\t}\n\t\tlet res: HTMLImageElement | HTMLVideoElement | null = null;\n\t\tlet blob: Blob | null = null;\n\t\tlet remainRetryTimes = 5;\n\t\twhile (!res && remainRetryTimes > 0) {\n\t\t\ttry {\n\t\t\t\tif (typeof albumSource === \"string\") {\n\t\t\t\t\tif (!isVideo && \"createImageBitmap\" in window) {\n\t\t\t\t\t\t// 如果支持 createImageBitmap 且是图片,直接 fetch blob\n\t\t\t\t\t\tconst response = await fetch(albumSource);\n\t\t\t\t\t\tblob = await response.blob();\n\t\t\t\t\t\t// 仍然需要一个 HTMLImageElement 来获取原始宽高(如果后续需要)\n\t\t\t\t\t\t// 但这里我们主要依赖 blob 来创建 bitmap\n\t\t\t\t\t\tres = await loadResourceFromUrl(URL.createObjectURL(blob), false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tres = await loadResourceFromUrl(albumSource, isVideo);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tres = await loadResourceFromElement(albumSource);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`failed on loading album resource, retrying (${remainRetryTimes})`,\n\t\t\t\t\t{\n\t\t\t\t\t\talbumSource,\n\t\t\t\t\t\terror,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tremainRetryTimes--;\n\t\t\t}\n\t\t}\n\t\tif (!res) {\n\t\t\tconsole.error(\"Failed to load album resource\", albumSource);\n\t\t\tthis.isNoCover = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.isNoCover = false;\n\t\t// resize image\n\t\tconst c = this.reduceImageSizeCanvas;\n\t\tconst ctx = c.getContext(\"2d\", {\n\t\t\twillReadFrequently: true,\n\t\t});\n\t\tif (!ctx) throw new Error(\"Failed to create canvas context\");\n\t\tctx.clearRect(0, 0, c.width, c.height);\n\t\t// Safari 不支持 filter\n\t\t// ctx.filter = baseFilter;\n\t\tconst imgw =\n\t\t\tres instanceof HTMLVideoElement ? res.videoWidth : res.naturalWidth;\n\t\tconst imgh =\n\t\t\tres instanceof HTMLVideoElement ? res.videoHeight : res.naturalHeight;\n\t\tif (imgw * imgh === 0) throw new Error(\"Invalid image size\");\n\n\t\tlet bitmap: ImageBitmap | null = null;\n\t\ttry {\n\t\t\tif (\"createImageBitmap\" in window) {\n\t\t\t\t// 避免在主线程进行同步解码,使用 fetch 获取 blob 后再创建 ImageBitmap\n\t\t\t\tif (blob) {\n\t\t\t\t\tbitmap = await createImageBitmap(blob, {\n\t\t\t\t\t\tresizeWidth: c.width,\n\t\t\t\t\t\tresizeHeight: c.height,\n\t\t\t\t\t\tresizeQuality: \"low\",\n\t\t\t\t\t});\n\t\t\t\t\tURL.revokeObjectURL(res.src); // 释放 object URL\n\t\t\t\t} else {\n\t\t\t\t\tbitmap = await createImageBitmap(res, {\n\t\t\t\t\t\tresizeWidth: c.width,\n\t\t\t\t\t\tresizeHeight: c.height,\n\t\t\t\t\t\tresizeQuality: \"low\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.warn(\"createImageBitmap failed\", e);\n\t\t}\n\n\t\tif (bitmap) {\n\t\t\tctx.drawImage(bitmap, 0, 0);\n\t\t\tbitmap.close();\n\t\t} else {\n\t\t\tctx.drawImage(res, 0, 0, imgw, imgh, 0, 0, c.width, c.height);\n\t\t}\n\n\t\tconst imageData = ctx.getImageData(0, 0, c.width, c.height);\n\n\t\t// 合并对比度、饱和度、亮度的处理,减少循环次数\n\t\tconst pixels = imageData.data;\n\t\tfor (let i = 0; i < pixels.length; i += 4) {\n\t\t\tlet r = pixels[i];\n\t\t\tlet g = pixels[i + 1];\n\t\t\tlet b = pixels[i + 2];\n\n\t\t\t// contrast 0.4\n\t\t\tr = (r - 128) * 0.4 + 128;\n\t\t\tg = (g - 128) * 0.4 + 128;\n\t\t\tb = (b - 128) * 0.4 + 128;\n\n\t\t\t// saturate 3.0\n\t\t\tconst gray = r * 0.3 + g * 0.59 + b * 0.11;\n\t\t\tr = gray * -2.0 + r * 3.0;\n\t\t\tg = gray * -2.0 + g * 3.0;\n\t\t\tb = gray * -2.0 + b * 3.0;\n\n\t\t\t// contrast 1.7\n\t\t\tr = (r - 128) * 1.7 + 128;\n\t\t\tg = (g - 128) * 1.7 + 128;\n\t\t\tb = (b - 128) * 1.7 + 128;\n\n\t\t\t// brightness 0.75\n\t\t\tpixels[i] = r * 0.75;\n\t\t\tpixels[i + 1] = g * 0.75;\n\t\t\tpixels[i + 2] = b * 0.75;\n\t\t}\n\n\t\tblurImage(imageData, 2, 4);\n\n\t\tif (this.manualControl && this.meshStates.length > 0) {\n\t\t\tthis.meshStates[0].texture.dispose();\n\t\t\tthis.meshStates[0].texture = new GLTexture(this.gl, imageData);\n\t\t} else {\n\t\t\tconst newMesh = new BHPMesh(\n\t\t\t\tthis.gl,\n\t\t\t\tthis.mainProgram.attrs.a_pos,\n\t\t\t\tthis.mainProgram.attrs.a_color,\n\t\t\t\tthis.mainProgram.attrs.a_uv,\n\t\t\t);\n\t\t\tnewMesh.resetSubdivition(50);\n\n\t\t\tconst chosenPreset =\n\t\t\t\tMath.random() > 0.8\n\t\t\t\t\t? generateControlPoints(6, 6)\n\t\t\t\t\t: CONTROL_POINT_PRESETS[\n\t\t\t\t\t\t\tMath.floor(Math.random() * CONTROL_POINT_PRESETS.length)\n\t\t\t\t\t\t];\n\n\t\t\tnewMesh.resizeControlPoints(chosenPreset.width, chosenPreset.height);\n\t\t\tconst uPower = 2 / (chosenPreset.width - 1);\n\t\t\tconst vPower = 2 / (chosenPreset.height - 1);\n\t\t\tfor (const cp of chosenPreset.conf) {\n\t\t\t\tconst p = newMesh.getControlPoint(cp.cx, cp.cy);\n\t\t\t\tp.location.x = cp.x;\n\t\t\t\tp.location.y = cp.y;\n\t\t\t\tp.uRot = (cp.ur * Math.PI) / 180;\n\t\t\t\tp.vRot = (cp.vr * Math.PI) / 180;\n\t\t\t\tp.uScale = uPower * cp.up;\n\t\t\t\tp.vScale = vPower * cp.vp;\n\t\t\t}\n\n\t\t\tnewMesh.updateMesh();\n\t\t\t// this.currentImageData = imageData;\n\n\t\t\tconst albumTexture = new GLTexture(this.gl, imageData);\n\t\t\tconst newState: MeshState = {\n\t\t\t\tmesh: newMesh,\n\t\t\t\ttexture: albumTexture,\n\t\t\t\talpha: 0,\n\t\t\t};\n\t\t\tthis.meshStates.push(newState);\n\t\t}\n\n\t\tthis.requestTick();\n\t}\n\toverride setLowFreqVolume(volume: number): void {\n\t\tthis.volume = volume / 10;\n\t}\n\toverride setHasLyric(_hasLyric: boolean): void {\n\t\t// 不再考虑实现\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tif (this.tickHandle) {\n\t\t\tcancelAnimationFrame(this.tickHandle);\n\t\t\tthis.tickHandle = 0;\n\t\t}\n\t\tthis._disposed = true;\n\t\tthis.mainProgram.dispose();\n\t\tthis.quadProgram.dispose();\n\t\tthis.gl.deleteBuffer(this.quadBuffer);\n\t\tif (this.fbo) this.gl.deleteFramebuffer(this.fbo);\n\t\tif (this.fboTexture) this.gl.deleteTexture(this.fboTexture);\n\t\tfor (const state of this.meshStates) {\n\t\t\tstate.mesh.dispose();\n\t\t\tstate.texture.dispose();\n\t\t}\n\t}\n\n\tenablePerformanceMonitor(enable: boolean): void {\n\t\tthis.enablePerformanceMonitoring = enable;\n\t\tif (enable) {\n\t\t\tthis.frameCount = 0;\n\t\t\tthis.lastFPSUpdate = performance.now();\n\t\t}\n\t}\n\n\tgetCurrentFPS(): number {\n\t\treturn this.currentFPS;\n\t}\n\n\tprivate updatePerformanceStats(tickTime: number) {\n\t\tif (!this.enablePerformanceMonitoring) return;\n\n\t\tthis.frameCount++;\n\t\tif (tickTime - this.lastFPSUpdate > 1000) {\n\t\t\tthis.currentFPS = this.frameCount;\n\t\t\tthis.frameCount = 0;\n\t\t\tthis.lastFPSUpdate = tickTime;\n\t\t}\n\t}\n}\n","import { Application } from \"@pixi/app\";\nimport { Texture } from \"@pixi/core\";\nimport { Container } from \"@pixi/display\";\nimport { BlurFilter } from \"@pixi/filter-blur\";\nimport { BulgePinchFilter } from \"@pixi/filter-bulge-pinch\";\nimport { ColorMatrixFilter } from \"@pixi/filter-color-matrix\";\nimport { Sprite } from \"@pixi/sprite\";\nimport {\n\tloadResourceFromElement,\n\tloadResourceFromUrl,\n} from \"../utils/resource\";\nimport { BaseRenderer } from \"./base\";\nimport { clampPositive } from \"#utils/clamp.ts\";\n\nclass TimedContainer extends Container {\n\tpublic time = 0;\n}\n\nexport class PixiRenderer extends BaseRenderer {\n\tprivate app: Application;\n\tprivate curContainer?: TimedContainer;\n\tprivate staticMode = false;\n\tprivate lastContainer: Set<TimedContainer> = new Set();\n\tprivate onTick = (delta: number): void => {\n\t\tfor (const lastContainer of this.lastContainer) {\n\t\t\tlastContainer.alpha = clampPositive(lastContainer.alpha - delta / 60);\n\t\t\tif (lastContainer.alpha <= 0) {\n\t\t\t\tthis.app.stage.removeChild(lastContainer);\n\t\t\t\tthis.lastContainer.delete(lastContainer);\n\t\t\t\tlastContainer.destroy(true);\n\t\t\t}\n\t\t}\n\n\t\tif (this.curContainer) {\n\t\t\tthis.curContainer.alpha = Math.min(\n\t\t\t\t1,\n\t\t\t\tthis.curContainer.alpha + delta / 60,\n\t\t\t);\n\t\t\tconst [s1, s2, s3, s4] = this.curContainer.children as Sprite[];\n\t\t\tconst maxSize = Math.max(this.app.screen.width, this.app.screen.height);\n\t\t\ts1.position.set(this.app.screen.width / 2, this.app.screen.height / 2);\n\t\t\ts2.position.set(\n\t\t\t\tthis.app.screen.width / 2.5,\n\t\t\t\tthis.app.screen.height / 2.5,\n\t\t\t);\n\t\t\ts3.position.set(this.app.screen.width / 2, this.app.screen.height / 2);\n\t\t\ts4.position.set(this.app.screen.width / 2, this.app.screen.height / 2);\n\t\t\ts1.width = maxSize * Math.sqrt(2);\n\t\t\ts1.height = s1.width;\n\t\t\ts2.width = maxSize * 0.8;\n\t\t\ts2.height = s2.width;\n\t\t\ts3.width = maxSize * 0.5;\n\t\t\ts3.height = s3.width;\n\t\t\ts4.width = maxSize * 0.25;\n\t\t\ts4.height = s4.width;\n\n\t\t\tthis.curContainer.time += delta * this.flowSpeed;\n\n\t\t\ts1.rotation += (delta / 1000) * this.flowSpeed;\n\t\t\ts2.rotation -= (delta / 500) * this.flowSpeed;\n\t\t\ts3.rotation += (delta / 1000) * this.flowSpeed;\n\t\t\ts4.rotation -= (delta / 750) * this.flowSpeed;\n\n\t\t\ts3.x =\n\t\t\t\tthis.app.screen.width / 2 +\n\t\t\t\t(this.app.screen.width / 4) *\n\t\t\t\t\tMath.cos((this.curContainer.time / 1000) * 0.75);\n\t\t\ts3.y =\n\t\t\t\tthis.app.screen.height / 2 +\n\t\t\t\t(this.app.screen.width / 4) *\n\t\t\t\t\tMath.cos((this.curContainer.time / 1000) * 0.75);\n\n\t\t\ts4.x =\n\t\t\t\tthis.app.screen.width / 2 +\n\t\t\t\t(this.app.screen.width / 4) * 0.1 +\n\t\t\t\tMath.cos(this.curContainer.time * 0.006 * 0.75);\n\t\t\ts4.y =\n\t\t\t\tthis.app.screen.height / 2 +\n\t\t\t\t(this.app.screen.width / 4) * 0.1 +\n\t\t\t\tMath.cos(this.curContainer.time * 0.006 * 0.75);\n\n\t\t\tif (\n\t\t\t\tthis.curContainer.alpha >= 1 &&\n\t\t\t\tthis.lastContainer.size === 0 &&\n\t\t\t\tthis.staticMode\n\t\t\t) {\n\t\t\t\tthis.app.ticker.stop();\n\t\t\t}\n\t\t}\n\t};\n\tconstructor(protected override canvas: HTMLCanvasElement) {\n\t\tsuper(canvas);\n\t\tthis.app = new Application({\n\t\t\tview: canvas,\n\t\t\tresizeTo: this.canvas,\n\t\t\tpowerPreference: \"low-power\",\n\t\t\tbackgroundAlpha: 1,\n\t\t});\n\t\tthis.rebuildFilters();\n\t\tthis.app.ticker.maxFPS = 30;\n\t\tthis.app.ticker.add(this.onTick);\n\t\tthis.app.ticker.start();\n\t}\n\n\tprotected override onResize(width: number, height: number): void {\n\t\tsuper.onResize(width, height);\n\t\tthis.app.resize();\n\t\tthis.rebuildFilters();\n\t}\n\n\toverride setRenderScale(scale: number): void {\n\t\tsuper.setRenderScale(scale);\n\t\tthis.rebuildFilters();\n\t}\n\tprivate rebuildFilters() {\n\t\tconst minBorder = Math.min(this.canvas.width, this.canvas.height);\n\t\tconst maxBorder = Math.max(this.canvas.width, this.canvas.height);\n\t\tconst c0 = new ColorMatrixFilter();\n\t\tc0.saturate(1.2, false);\n\t\tconst c1 = new ColorMatrixFilter();\n\t\tc1.brightness(0.6, false);\n\t\tconst c2 = new ColorMatrixFilter();\n\t\tc2.contrast(0.3, true);\n\t\tfor (const filter of this.app.stage.filters ?? []) {\n\t\t\tfilter.destroy();\n\t\t}\n\t\tthis.app.stage.filters = [];\n\t\tthis.app.stage.filters.push(new BlurFilter(5, 1));\n\t\tthis.app.stage.filters.push(new BlurFilter(10, 1));\n\t\tthis.app.stage.filters.push(new BlurFilter(20, 2));\n\t\tthis.app.stage.filters.push(new BlurFilter(40, 2));\n\t\tthis.app.stage.filters.push(new BlurFilter(80, 2));\n\t\tif (minBorder > 768) this.app.stage.filters.push(new BlurFilter(160, 4));\n\t\tif (minBorder > 768 * 2)\n\t\t\tthis.app.stage.filters.push(new BlurFilter(320, 4));\n\n\t\tthis.app.stage.filters.push(c0, c1, c2);\n\t\tthis.app.stage.filters.push(new BlurFilter(5, 1));\n\t\tif (Math.random() > 0.5) {\n\t\t\tthis.app.stage.filters.push(\n\t\t\t\tnew BulgePinchFilter({\n\t\t\t\t\tradius: (maxBorder + minBorder) / 2,\n\t\t\t\t\tstrength: 1,\n\t\t\t\t\tcenter: [0.25, 1],\n\t\t\t\t}),\n\t\t\t);\n\t\t\tthis.app.stage.filters.push(\n\t\t\t\tnew BulgePinchFilter({\n\t\t\t\t\tradius: (maxBorder + minBorder) / 2,\n\t\t\t\t\tstrength: 1,\n\t\t\t\t\tcenter: [0.75, 0],\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tthis.app.stage.filters.push(\n\t\t\t\tnew BulgePinchFilter({\n\t\t\t\t\tradius: (maxBorder + minBorder) / 2,\n\t\t\t\t\tstrength: 1,\n\t\t\t\t\tcenter: [0.75, 1],\n\t\t\t\t}),\n\t\t\t);\n\t\t\tthis.app.stage.filters.push(\n\t\t\t\tnew BulgePinchFilter({\n\t\t\t\t\tradius: (maxBorder + minBorder) / 2,\n\t\t\t\t\tstrength: 1,\n\t\t\t\t\tcenter: [0.25, 0],\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\toverride setStaticMode(enable = false): void {\n\t\tthis.staticMode = enable;\n\t\tthis.app.ticker.start();\n\t}\n\n\toverride setFPS(fps: number): void {\n\t\tthis.app.ticker.maxFPS = fps;\n\t}\n\n\toverride pause(): void {\n\t\tthis.app.ticker.stop();\n\t\tthis.app.render();\n\t}\n\n\toverride resume(): void {\n\t\tthis.app.ticker.start();\n\t}\n\n\toverride setLowFreqVolume(_volume: number): void {\n\t\t// NOOP\n\t}\n\n\toverride setHasLyric(_hasLyric: boolean): void {\n\t\t// NOOP\n\t}\n\n\toverride async setAlbum(\n\t\talbumSource?: string | HTMLImageElement | HTMLVideoElement,\n\t\tisVideo?: boolean,\n\t): Promise<void> {\n\t\tif (\n\t\t\t!albumSource ||\n\t\t\t(typeof albumSource === \"string\" && albumSource.trim().length === 0)\n\t\t)\n\t\t\treturn;\n\t\tlet res: HTMLImageElement | HTMLVideoElement | null = null;\n\t\tlet remainRetryTimes = 5;\n\t\tlet tex: Texture | null = null;\n\t\twhile (!tex?.baseTexture?.resource?.valid && remainRetryTimes > 0) {\n\t\t\ttry {\n\t\t\t\tif (typeof albumSource === \"string\") {\n\t\t\t\t\tres = await loadResourceFromUrl(albumSource, isVideo);\n\t\t\t\t} else {\n\t\t\t\t\tres = await loadResourceFromElement(albumSource);\n\t\t\t\t}\n\t\t\t\ttex = Texture.from(res, {\n\t\t\t\t\tresourceOptions: {\n\t\t\t\t\t\tautoLoad: false,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tawait tex.baseTexture.resource.load();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`failed on loading album image, retrying (${remainRetryTimes})`,\n\t\t\t\t\talbumSource,\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\ttex = null;\n\t\t\t\tremainRetryTimes--;\n\t\t\t}\n\t\t}\n\t\tif (!tex) return;\n\t\tconst container = new TimedContainer();\n\t\tconst s1 = new Sprite(tex);\n\t\tconst s2 = new Sprite(tex);\n\t\tconst s3 = new Sprite(tex);\n\t\tconst s4 = new Sprite(tex);\n\t\ts1.anchor.set(0.5, 0.5);\n\t\ts2.anchor.set(0.5, 0.5);\n\t\ts3.anchor.set(0.5, 0.5);\n\t\ts4.anchor.set(0.5, 0.5);\n\t\ts1.rotation = Math.random() * Math.PI * 2;\n\t\ts2.rotation = Math.random() * Math.PI * 2;\n\t\ts3.rotation = Math.random() * Math.PI * 2;\n\t\ts4.rotation = Math.random() * Math.PI * 2;\n\t\tcontainer.addChild(s1, s2, s3, s4);\n\t\tif (this.curContainer) this.lastContainer.add(this.curContainer);\n\t\tthis.curContainer = container;\n\t\tthis.app.stage.addChild(container);\n\t\tthis.curContainer.alpha = 0;\n\t\tthis.app.ticker.start();\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tthis.app.ticker.remove(this.onTick);\n\t\tthis.app.destroy(true);\n\t}\n\n\toverride getElement(): HTMLElement {\n\t\treturn this.canvas;\n\t}\n}\n","/**\n * @fileoverview\n * 一个播放歌词的组件\n * @author SteveXMH\n */\n\nexport { AbstractBaseRenderer, BaseRenderer } from \"./base.ts\";\nexport { MeshGradientRenderer } from \"./mesh-renderer/index.ts\";\nexport { PixiRenderer } from \"./pixi-renderer.ts\";\nimport type { AbstractBaseRenderer, BaseRenderer } from \"./base.ts\";\n\nexport class BackgroundRender<Renderer extends BaseRenderer>\n\timplements AbstractBaseRenderer\n{\n\tprivate element: HTMLCanvasElement;\n\tprivate renderer: Renderer;\n\tconstructor(renderer: Renderer, canvas: HTMLCanvasElement) {\n\t\tthis.renderer = renderer;\n\n\t\tthis.element = canvas;\n\t\tcanvas.style.pointerEvents = \"none\";\n\t\tcanvas.style.zIndex = \"-1\";\n\t\tcanvas.style.contain = \"strict\";\n\t}\n\n\tstatic new<Renderer extends BaseRenderer>(type: {\n\t\tnew (canvas: HTMLCanvasElement): Renderer;\n\t}): BackgroundRender<Renderer> {\n\t\tconst newCanvas = document.createElement(\"canvas\");\n\t\treturn new BackgroundRender(new type(newCanvas), newCanvas);\n\t}\n\n\tsetRenderScale(scale: number): void {\n\t\tthis.renderer.setRenderScale(scale);\n\t}\n\n\tsetFlowSpeed(speed: number): void {\n\t\tthis.renderer.setFlowSpeed(speed);\n\t}\n\tsetStaticMode(enable: boolean): void {\n\t\tthis.renderer.setStaticMode(enable);\n\t}\n\tsetFPS(fps: number): void {\n\t\tthis.renderer.setFPS(fps);\n\t}\n\tpause(): void {\n\t\tthis.renderer.pause();\n\t}\n\tresume(): void {\n\t\tthis.renderer.resume();\n\t}\n\tsetLowFreqVolume(volume: number): void {\n\t\tthis.renderer.setLowFreqVolume(volume);\n\t}\n\tsetHasLyric(hasLyric: boolean): void {\n\t\tthis.renderer.setHasLyric(hasLyric);\n\t}\n\tsetAlbum(\n\t\talbumSource: string | HTMLImageElement | HTMLVideoElement,\n\t\tisVideo?: boolean,\n\t): Promise<void> {\n\t\treturn this.renderer.setAlbum(albumSource, isVideo);\n\t}\n\tgetElement(): HTMLCanvasElement {\n\t\treturn this.element;\n\t}\n\tdispose(): void {\n\t\tthis.renderer.dispose();\n\t\tthis.element.remove();\n\t}\n}\n",".lyricLineWrapper {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: flex-start;\n\twidth: 100%;\n\n\twill-change: transform, opacity, filter;\n\ttransition:\n\t\topacity 0.4s ease,\n\t\tfilter 0.4s ease;\n}\n\n.lyricLine {\n\tposition: relative;\n\tbox-sizing: border-box;\n\twidth: var(--amll-lp-width, 100%);\n\tmin-width: var(--amll-lp-width, 100%);\n\tmax-width: var(--amll-lp-width, 100%);\n\theight: fit-content;\n\tpadding: 0.5em 1em;\n\tpadding-left: 1em;\n\tpadding-right: 1em;\n\tborder-radius: 0.25em;\n\n\tcontain: content;\n\tbackface-visibility: hidden;\n\ttransform-origin: left;\n\twill-change: transform;\n\n\ttransition:\n\t\tbackground-color 0.25s,\n\t\tbox-shadow 0.25s;\n\n\t@media screen and (max-width: 500px) {\n\t\tpadding-left: 20px;\n\t\tpadding-right: 20px;\n\t}\n\n\t&.dirty {\n\t\topacity: 0;\n\t\tvisibility: hidden;\n\t}\n\n\t&:has(> *):hover {\n\t\tbackground-color: var(--amll-lp-hover-bg-color, #fff1);\n\t}\n\n\t&:has(> *):active {\n\t\tbackground-color: var(--amll-lp-hover-bg-color, #ffffff05);\n\t}\n}\n\n.lyricDuetLine {\n\ttext-align: right;\n\ttransform-origin: right;\n}\n\n.lyricMainLine {\n\tmargin: -1em;\n\tpadding: 1em;\n\ttransition: opacity 0.3s 0.1s;\n\n\t& span {\n\t\tdisplay: inline-block;\n\t\ttext-align: start;\n\t\tvertical-align: bottom;\n\t}\n\n\t.romanWord {\n\t\tdisplay: flex;\n\t\tpadding-inline-end: 0.3em;\n\t\tfont-size: 0.5em;\n\t\tline-height: 1em;\n\t}\n\n\t.rubyWord {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\tmin-height: 1em;\n\t\tfont-size: 0.5em;\n\t\tline-height: 1em;\n\t}\n\n\t.wordWithRuby {\n\t\tdisplay: inline-flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tvertical-align: bottom;\n\t}\n\n\t.wordBody {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t}\n\n\t& > span,\n\tspan.emphasizeWrapper {\n\t\tdisplay: inline-block;\n\t\tmargin: -1em;\n\t\tpadding: 1em;\n\t\twhite-space: pre-wrap;\n\t\tvertical-align: bottom;\n\t\twill-change: transform;\n\n\t\t&.emphasize,\n\t\tspan.emphasize {\n\t\t\tmargin: -1em;\n\t\t\tpadding: 1em;\n\t\t\tbackface-visibility: hidden;\n\n\t\t\t& > span {\n\t\t\t\tmargin: -1em;\n\t\t\t\tpadding: 1em;\n\t\t\t\twill-change: transform;\n\t\t\t\tbackface-visibility: hidden;\n\t\t\t}\n\t\t}\n\t}\n}\n\n.lyricBgLine {\n\topacity: 0.4;\n\t/* 因为字体大小缩小了,故内边距要和主行字体大小统一,行边距计算公式为 100% / font-size 转 em 单位 */\n\tpadding: 1vh\n\t\tcalc(var(--amll-lp-line-padding-x, 1em) / var(--amll-lp-bg-line-scale, 0.7));\n\tfont-size: max(calc(1em * var(--amll-lp-bg-line-scale, 0.7)), 10px);\n\ttransition:\n\t\tbackground-color 0.25s,\n\t\tbox-shadow 0.25s;\n\n\t.lyricMainLine {\n\t\tpadding: 1.2em 1em;\n\t}\n\n\t&.active {\n\t\topacity: 0.4;\n\t\ttransition:\n\t\t\tbackground-color 0.25s,\n\t\t\tbox-shadow 0.25s;\n\t}\n}\n\n.lyricSubLine {\n\topacity: 0.3;\n\tfont-size: max(0.5em, 10px);\n\tline-height: 1.5em;\n\ttransition: opacity 0.2s 0.25s;\n\n\t@supports (mix-blend-mode: plus-lighter) {\n\t\topacity: 0.3;\n\t}\n}\n\n.bottomLine {\n\tpadding-top: 0;\n\tpadding-bottom: 0;\n\tline-height: 1.8em;\n\tcursor: default;\n\n\t&:empty {\n\t\tdisplay: none;\n\t\theight: 0;\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t}\n}\n\n.bgWrapper {\n\tposition: absolute;\n\ttop: 100%;\n\tleft: 0;\n\tz-index: -1;\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: inherit;\n\twidth: 100%;\n\n\tvisibility: visible;\n\tpointer-events: auto;\n\topacity: 0;\n\ttransform-origin: var(--lyric-line-padding-x) top;\n\ttransition: opacity 0.3s ease;\n}\n\n.bgWrapperTop {\n\tposition: relative;\n\ttop: auto;\n\tbottom: auto;\n\tmargin-top: -999px;\n\ttransform-origin: var(--lyric-line-padding-x) bottom;\n}\n\n.bgWrapperActive {\n\tposition: relative;\n\ttop: auto;\n\tbottom: auto;\n\topacity: 1;\n}\n\n.bgWrapperHidden {\n\tvisibility: hidden;\n\tpointer-events: none;\n}\n\n.interludeDots {\n\tposition: absolute;\n\tleft: 0;\n\tdisplay: flex;\n\tgap: 0.25em;\n\twidth: fit-content;\n\theight: clamp(0.5em, 1vh, 3em);\n\tpadding: 2.5% 0.75em;\n\n\topacity: 0;\n\ttransform-origin: center;\n\ttransition: opacity 0.25s;\n\n\t&.enabled {\n\t\topacity: 1;\n\t}\n\n\t& > * {\n\t\tdisplay: inline-block;\n\t\twidth: clamp(0.5em, 1vh, 3em);\n\t\theight: clamp(0.5em, 1vh, 3em);\n\t\tmargin-right: 4px;\n\t\tborder-radius: 50%;\n\t\tbackground-color: var(--amll-lp-color, white);\n\t\taspect-ratio: 1 / 1;\n\t}\n\n\t&.duet {\n\t\tright: 0;\n\t\ttransform-origin: center;\n\t}\n}\n\n.disableSpring > *,\n.disableSpring .lyricLine {\n\ttransition:\n\t\tfilter 0.25s,\n\t\ttransform 0.5s,\n\t\tbackground-color 0.25s,\n\t\tbox-shadow 0.25s;\n}\n\n.tmpDisableTransition {\n\t/* biome-ignore lint/complexity/noImportantStyles: 覆盖内联样式 */\n\ttransition: none !important;\n}\n\n:global(.amll-lyric-player) {\n\t--lyric-line-padding-x: 1em;\n\n\t@media screen and (max-width: 500px) {\n\t\t--lyric-line-padding-x: 20px;\n\t}\n\n\t&:hover .lyricLine,\n\t&:hover .lyricLineWrapper {\n\t\t/* biome-ignore lint/complexity/noImportantStyles: 覆盖内联样式 */\n\t\tfilter: unset !important;\n\t}\n\n\t&.hasDuetLine {\n\t\t.lyricLine:not(.lyricDuetLine) {\n\t\t\tpadding-right: 15%;\n\t\t}\n\n\t\t.lyricDuetLine {\n\t\t\tpadding-left: 15%;\n\t\t}\n\n\t\t.lyricLineWrapper:has(.lyricDuetLine) {\n\t\t\talign-items: flex-end;\n\n\t\t\t.bgWrapper {\n\t\t\t\ttransform-origin: calc(100% - var(--lyric-line-padding-x)) top;\n\t\t\t}\n\n\t\t\t.bgWrapperTop {\n\t\t\t\ttransform-origin: calc(100% - var(--lyric-line-padding-x)) bottom;\n\t\t\t}\n\t\t}\n\t}\n\n\t&:not(.playing) .bgWrapper {\n\t\tposition: relative;\n\t\ttop: auto;\n\t\tbottom: auto;\n\t\topacity: 1;\n\t}\n}\n","import type { LyricLine, OptimizeLyricOptions } from \"../interfaces.ts\";\n\nconst DEFAULT_OPTIMIZE_OPTIONS: OptimizeLyricOptions = {\n\tnormalizeSpaces: true,\n\tresetLineTimestamps: true,\n\tconvertExcessiveBackgroundLines: true,\n\tsyncMainAndBackgroundLines: true,\n\tcleanUnintentionalOverlaps: true,\n\ttryAdvanceStartTime: true,\n};\n\n/**\n * 规范化歌词中的空格,将多个连续空格替换为一个空格\n */\nfunction normalizeSpaces(lines: LyricLine[]) {\n\tfor (const line of lines) {\n\t\tfor (const word of line.words) {\n\t\t\tword.word = word.word.replace(/\\s+/g, \" \");\n\t\t}\n\t}\n}\n\n/**\n * 将行级时间戳强行设为字级时间戳\n */\nfunction resetLineTimestamps(lines: LyricLine[]) {\n\tfor (const line of lines) {\n\t\t// 主要是给 TTML 解析器打补丁,其解析逐行歌词时获得的词时间戳均为0\n\t\t// 如果只有一个词,且该词的起止时间均为0,且行时间戳不全为0,则将行时间戳同步给词时间戳\n\t\tif (\n\t\t\tline.words.length === 1 &&\n\t\t\tline.words[0].startTime === 0 &&\n\t\t\tline.words[0].endTime === 0 &&\n\t\t\t(line.startTime !== 0 || line.endTime !== 0)\n\t\t) {\n\t\t\tline.words[0].startTime = line.startTime;\n\t\t\tline.words[0].endTime = line.endTime;\n\t\t} else if (line.words.length > 0) {\n\t\t\tconst firstWord = line.words[0];\n\t\t\tconst lastWord = line.words[line.words.length - 1];\n\n\t\t\tline.startTime = firstWord.startTime;\n\t\t\tline.endTime = lastWord.endTime;\n\t\t}\n\t}\n}\n\n/**\n * 把多行背景人声转换为单行背景人声 + 主歌词行的形式\n */\nfunction convertExcessiveBackgroundLines(lines: LyricLine[]) {\n\tlet consecutiveBgCount = 0;\n\n\tfor (const line of lines) {\n\t\tif (line.isBG) {\n\t\t\tconsecutiveBgCount++;\n\t\t\tif (consecutiveBgCount > 1) {\n\t\t\t\tline.isBG = false;\n\t\t\t}\n\t\t} else {\n\t\t\tconsecutiveBgCount = 0;\n\t\t}\n\t}\n}\n\n/**\n * 同步主歌词与背景人声的时间\n *\n * 取两者中最早的开始时间和最晚的结束时间,应用给双方\n */\nfunction syncMainAndBackgroundLines(lines: LyricLine[]) {\n\tfor (let i = lines.length - 1; i >= 0; i--) {\n\t\tconst line = lines[i];\n\t\tif (line.isBG) continue;\n\n\t\tconst nextLine = lines[i + 1];\n\t\tif (nextLine?.isBG) {\n\t\t\tconst allWords = [...line.words, ...nextLine.words].filter(\n\t\t\t\t(w) => w.word.trim().length > 0,\n\t\t\t);\n\n\t\t\tif (allWords.length > 0) {\n\t\t\t\tconst minStart = Math.min(...allWords.map((w) => w.startTime));\n\t\t\t\tconst maxEnd = Math.max(...allWords.map((w) => w.endTime));\n\n\t\t\t\tconst finalStart = Math.min(\n\t\t\t\t\tminStart,\n\t\t\t\t\tline.startTime,\n\t\t\t\t\tnextLine.startTime,\n\t\t\t\t);\n\t\t\t\tconst finalEnd = Math.max(maxEnd, line.endTime, nextLine.endTime);\n\n\t\t\t\tline.startTime = finalStart;\n\t\t\t\tline.endTime = finalEnd;\n\t\t\t\tnextLine.startTime = finalStart;\n\t\t\t\tnextLine.endTime = finalEnd;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * 清洗非刻意的重叠\n *\n * 如果重叠大于100ms 且 重叠超过下一行时长的10%,则视为刻意重叠,否则将结束时间设为下一行的开始时间\n */\nfunction cleanUnintentionalOverlaps(lines: LyricLine[]) {\n\tfor (let i = 0; i < lines.length - 1; i++) {\n\t\tconst line = lines[i];\n\t\tif (line.isBG) continue;\n\n\t\tlet nextMainIndex = i + 1;\n\t\twhile (nextMainIndex < lines.length && lines[nextMainIndex].isBG) {\n\t\t\tnextMainIndex++;\n\t\t}\n\n\t\tif (nextMainIndex < lines.length) {\n\t\t\tconst nextLine = lines[nextMainIndex];\n\t\t\tconst overlap = line.endTime - nextLine.startTime;\n\n\t\t\tif (overlap > 0) {\n\t\t\t\tconst nextDuration = nextLine.endTime - nextLine.startTime;\n\t\t\t\tconst percentageThreshold = nextDuration * 0.1;\n\n\t\t\t\t// 重叠大于100ms 且 重叠超过下一行时长的10%\n\t\t\t\tconst isIntentionalOverlap =\n\t\t\t\t\toverlap > 100 && overlap > percentageThreshold;\n\n\t\t\t\tif (!isIntentionalOverlap) {\n\t\t\t\t\tline.endTime = nextLine.startTime;\n\n\t\t\t\t\tconst attachedBgLine = lines[i + 1];\n\t\t\t\t\tif (attachedBgLine?.isBG) {\n\t\t\t\t\t\tattachedBgLine.endTime = nextLine.startTime;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * 尝试让歌词提前最多 600ms 开始,如果有重叠则尝试最多提前 400ms 或上一行时长的 30%\n */\nfunction tryAdvanceStartTime(lines: LyricLine[]) {\n\tconst defaultAdvanceAmount = 600;\n\tconst fallbackAdvanceAmount = 400;\n\tconst fallbackAdvanceRatio = 0.3;\n\n\tlet prevLineStartTime = 0;\n\tlet prevLineEndTime = 0;\n\tlet prevMainGroupStartTime = 0;\n\tlet prevMainGroupEndTime = 0;\n\tlet hasPrevLine = false;\n\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i];\n\t\tif (line.isBG) continue;\n\n\t\tconst originalStartTime = line.startTime;\n\t\tconst originalEndTime = line.endTime;\n\n\t\tlet targetAdvanceAmount = 0;\n\t\tlet safeBoundary = 0;\n\n\t\tif (hasPrevLine) {\n\t\t\tconst originallyHadGap = originalStartTime >= prevLineEndTime;\n\n\t\t\tif (originallyHadGap) {\n\t\t\t\ttargetAdvanceAmount = defaultAdvanceAmount;\n\t\t\t\tsafeBoundary = prevMainGroupEndTime;\n\t\t\t} else {\n\t\t\t\ttargetAdvanceAmount = fallbackAdvanceAmount;\n\t\t\t\tconst prevDuration = prevLineEndTime - prevLineStartTime;\n\t\t\t\tsafeBoundary = prevLineStartTime + prevDuration * fallbackAdvanceRatio;\n\t\t\t}\n\t\t} else {\n\t\t\ttargetAdvanceAmount = defaultAdvanceAmount;\n\t\t\tsafeBoundary = 0;\n\t\t}\n\n\t\tconst targetTime = line.startTime - targetAdvanceAmount;\n\t\tconst newStartTime = Math.max(safeBoundary, targetTime);\n\n\t\tif (newStartTime < line.startTime) {\n\t\t\tline.startTime = newStartTime;\n\t\t}\n\n\t\tconst nextLine = lines[i + 1];\n\t\tif (nextLine?.isBG) {\n\t\t\tnextLine.startTime = line.startTime;\n\t\t}\n\n\t\tif (hasPrevLine) {\n\t\t\tconst overlapsPrevGroup =\n\t\t\t\toriginalStartTime < prevMainGroupEndTime &&\n\t\t\t\toriginalEndTime > prevMainGroupStartTime;\n\n\t\t\tif (overlapsPrevGroup) {\n\t\t\t\tprevMainGroupStartTime = Math.min(\n\t\t\t\t\tprevMainGroupStartTime,\n\t\t\t\t\toriginalStartTime,\n\t\t\t\t);\n\t\t\t\tprevMainGroupEndTime = Math.max(prevMainGroupEndTime, originalEndTime);\n\t\t\t} else {\n\t\t\t\tprevMainGroupStartTime = originalStartTime;\n\t\t\t\tprevMainGroupEndTime = originalEndTime;\n\t\t\t}\n\t\t} else {\n\t\t\tprevMainGroupStartTime = originalStartTime;\n\t\t\tprevMainGroupEndTime = originalEndTime;\n\t\t}\n\n\t\tprevLineStartTime = originalStartTime;\n\t\tprevLineEndTime = originalEndTime;\n\t\thasPrevLine = true;\n\t}\n}\n\n/**\n * 优化歌词行的展示效果\n *\n * 注意会直接原地修改入参,确保你已经提前深克隆了歌词行数组\n * @param lines 歌词行数组\n * @param options 优化的可选配置,默认全部开启\n */\nexport function optimizeLyricLines(\n\tlines: LyricLine[],\n\toptions?: OptimizeLyricOptions,\n): void {\n\tconst config = { ...DEFAULT_OPTIMIZE_OPTIONS, ...options };\n\n\tif (config.normalizeSpaces) {\n\t\tnormalizeSpaces(lines);\n\t}\n\tif (config.resetLineTimestamps) {\n\t\tresetLineTimestamps(lines);\n\t}\n\tif (config.convertExcessiveBackgroundLines) {\n\t\tconvertExcessiveBackgroundLines(lines);\n\t}\n\tif (config.syncMainAndBackgroundLines) {\n\t\tsyncMainAndBackgroundLines(lines);\n\t}\n\tif (config.cleanUnintentionalOverlaps) {\n\t\tcleanUnintentionalOverlaps(lines);\n\t}\n\tif (config.tryAdvanceStartTime) {\n\t\ttryAdvanceStartTime(lines);\n\t}\n}\n","import type { Disposable, HasElement } from \"#interfaces\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { clamp, clamp01, clampPositive } from \"#utils/clamp.ts\";\n\nfunction easeInOutBack(x: number): number {\n\tconst c1 = 1.70158;\n\tconst c2 = c1 * 1.525;\n\n\treturn x < 0.5\n\t\t? ((2 * x) ** 2 * ((c2 + 1) * 2 * x - c2)) / 2\n\t\t: ((2 * x - 2) ** 2 * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2;\n}\n\nfunction easeOutExpo(x: number): number {\n\treturn x === 1 ? 1 : 1 - 2 ** (-10 * x);\n}\n\nexport class InterludeDots implements HasElement, Disposable {\n\tprivate element: HTMLElement = document.createElement(\"div\");\n\tprivate dot0: HTMLElement = document.createElement(\"span\");\n\tprivate dot1: HTMLElement = document.createElement(\"span\");\n\tprivate dot2: HTMLElement = document.createElement(\"span\");\n\tprivate left = 0;\n\tprivate top = 0;\n\tprivate playing = true;\n\tprivate lastStyle = \"\";\n\tprivate currentInterlude?: [number, number];\n\tprivate currentTime = 0;\n\tprivate targetBreatheDuration = 1500;\n\tconstructor() {\n\t\tthis.element.className = styles.interludeDots;\n\t\tthis.element.appendChild(this.dot0);\n\t\tthis.element.appendChild(this.dot1);\n\t\tthis.element.appendChild(this.dot2);\n\t}\n\tgetElement(): HTMLElement {\n\t\treturn this.element;\n\t}\n\tsetTransform(left: number = this.left, top: number = this.top): void {\n\t\tthis.left = left;\n\t\tthis.top = top;\n\t\tthis.update();\n\t}\n\tsetInterlude(interlude?: [number, number]): void {\n\t\tthis.currentInterlude = interlude;\n\t\tthis.currentTime = interlude?.[0] ?? 0;\n\t\tif (interlude) {\n\t\t\tthis.element.classList.add(styles.enabled);\n\t\t} else {\n\t\t\tthis.element.classList.remove(styles.enabled);\n\t\t}\n\t}\n\tpause(): void {\n\t\tthis.playing = false;\n\t\tthis.element.classList.remove(styles.playing);\n\t}\n\tresume(): void {\n\t\tthis.playing = true;\n\t\tthis.element.classList.add(styles.playing);\n\t}\n\tupdate(delta = 0): void {\n\t\tif (!this.playing) return;\n\t\tthis.currentTime += delta;\n\t\tlet curStyle = \"\";\n\n\t\tcurStyle += `transform:translate(${this.left.toFixed(\n\t\t\t2,\n\t\t)}px, ${this.top.toFixed(2)}px)`;\n\n\t\t// 计算缩放大小\n\n\t\tif (this.currentInterlude) {\n\t\t\tconst interludeDuration =\n\t\t\t\tthis.currentInterlude[1] - this.currentInterlude[0];\n\t\t\tconst currentDuration = this.currentTime - this.currentInterlude[0];\n\t\t\tif (currentDuration <= interludeDuration) {\n\t\t\t\tconst breatheDuration =\n\t\t\t\t\tinterludeDuration /\n\t\t\t\t\tMath.ceil(interludeDuration / this.targetBreatheDuration);\n\t\t\t\tlet scale = 1;\n\t\t\t\tlet globalOpacity = 1;\n\n\t\t\t\tscale *=\n\t\t\t\t\tMath.sin(1.5 * Math.PI - (currentDuration / breatheDuration) * 2) /\n\t\t\t\t\t\t20 +\n\t\t\t\t\t1;\n\n\t\t\t\tif (currentDuration < 2000) {\n\t\t\t\t\tscale *= easeOutExpo(currentDuration / 2000);\n\t\t\t\t}\n\n\t\t\t\tif (currentDuration < 500) {\n\t\t\t\t\tglobalOpacity = 0;\n\t\t\t\t} else if (currentDuration < 1000) {\n\t\t\t\t\tglobalOpacity *= (currentDuration - 500) / 500;\n\t\t\t\t}\n\n\t\t\t\tif (interludeDuration - currentDuration < 750) {\n\t\t\t\t\tscale *=\n\t\t\t\t\t\t1 -\n\t\t\t\t\t\teaseInOutBack(\n\t\t\t\t\t\t\t(750 - (interludeDuration - currentDuration)) / 750 / 2,\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (interludeDuration - currentDuration < 375) {\n\t\t\t\t\tglobalOpacity *= clamp01((interludeDuration - currentDuration) / 375);\n\t\t\t\t}\n\n\t\t\t\tconst dotsDuration = clampPositive(interludeDuration - 750);\n\n\t\t\t\tscale = clampPositive(scale) * 0.7;\n\n\t\t\t\tcurStyle += ` scale(${scale})`;\n\n\t\t\t\tconst dot0Opacity = clamp(\n\t\t\t\t\t0.25,\n\t\t\t\t\t((currentDuration * 3) / dotsDuration) * 0.75,\n\t\t\t\t\t1,\n\t\t\t\t);\n\t\t\t\tconst dot1Opacity = clamp(\n\t\t\t\t\t0.25,\n\t\t\t\t\t(((currentDuration - dotsDuration / 3) * 3) / dotsDuration) * 0.75,\n\t\t\t\t\t1,\n\t\t\t\t);\n\t\t\t\tconst dot2Opacity = clamp(\n\t\t\t\t\t0.25,\n\t\t\t\t\t(((currentDuration - (dotsDuration / 3) * 2) * 3) / dotsDuration) *\n\t\t\t\t\t\t0.75,\n\t\t\t\t\t1,\n\t\t\t\t);\n\n\t\t\t\tthis.dot0.style.opacity = `${clamp01(globalOpacity * dot0Opacity)}`;\n\t\t\t\tthis.dot1.style.opacity = `${clamp01(globalOpacity * dot1Opacity)}`;\n\t\t\t\tthis.dot2.style.opacity = `${clamp01(globalOpacity * dot2Opacity)}`;\n\t\t\t} else {\n\t\t\t\tcurStyle += \" scale(0)\";\n\t\t\t\tthis.dot0.style.opacity = \"0\";\n\t\t\t\tthis.dot1.style.opacity = \"0\";\n\t\t\t\tthis.dot2.style.opacity = \"0\";\n\t\t\t}\n\n\t\t\tcurStyle += \";\";\n\n\t\t\tif (this.lastStyle !== curStyle) {\n\t\t\t\tthis.element.setAttribute(\"style\", curStyle);\n\t\t\t\tthis.lastStyle = curStyle;\n\t\t\t}\n\t\t}\n\t}\n\tdispose(): void {\n\t\tthis.element.remove();\n\t}\n}\n","/**\n * @fileoverview\n * @see https://github.com/wilsonpage/fastdom/blob/master/fastdom.js\n */\n\ninterface Task<T> {\n\ttask: () => T;\n\tresolve: (value: T) => void;\n\treject: (reason?: unknown) => void;\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: util functions\nconst measureTasks: Task<any>[] = [];\n// biome-ignore lint/suspicious/noExplicitAny: util functions\nconst mutateTasks: Task<any>[] = [];\nlet scheduled = false;\n\nfunction onFlush() {\n\tlet tmp = mutateTasks.shift();\n\twhile (tmp) {\n\t\ttry {\n\t\t\ttmp.resolve(tmp.task());\n\t\t} catch (error) {\n\t\t\ttmp.reject(error);\n\t\t}\n\t\ttmp = mutateTasks.shift();\n\t}\n\ttmp = measureTasks.shift();\n\twhile (tmp) {\n\t\ttry {\n\t\t\ttmp.resolve(tmp.task());\n\t\t} catch (error) {\n\t\t\ttmp.reject(error);\n\t\t}\n\t\ttmp = measureTasks.shift();\n\t}\n\tscheduled = false;\n}\n\nfunction scheduleFlush() {\n\tif (!scheduled) {\n\t\tscheduled = true;\n\t\trequestAnimationFrame(onFlush);\n\t}\n}\n\nexport function measure<T>(callback: () => T): Promise<T> {\n\tconst task: Task<T> = {\n\t\ttask: callback,\n\t\tresolve: () => {},\n\t\treject: () => {},\n\t};\n\tconst promise = new Promise<T>((resolve, reject) => {\n\t\ttask.resolve = resolve;\n\t\ttask.reject = reject;\n\t});\n\tmeasureTasks.push(task);\n\tscheduleFlush();\n\treturn promise;\n}\n\nexport function mutate(callback: () => void): Promise<unknown> {\n\tconst task: Task<void> = {\n\t\ttask: callback,\n\t\tresolve: () => {},\n\t\treject: () => {},\n\t};\n\tconst promise = new Promise((resolve, reject) => {\n\t\ttask.resolve = resolve;\n\t\ttask.reject = reject;\n\t});\n\tmutateTasks.push(task);\n\tscheduleFlush();\n\treturn promise;\n}\n","export function derivative(f: (x: number) => number) {\n\tconst h = 0.001;\n\treturn (x: number): number => (f(x + h) - f(x - h)) / (2 * h);\n}\n\nexport function getVelocity(f: (t: number) => number): (t: number) => number {\n\treturn derivative(f);\n}\n","import { getVelocity } from \"./derivative.ts\";\n\n/** MIT License github.com/pushkine/ */\nexport interface SpringParams {\n\tmass: number; // = 1.0\n\tdamping: number; // = 10.0\n\tstiffness: number; // = 100.0\n\tsoft: boolean; // = false\n}\n\ntype seconds = number;\n\nexport class Spring {\n\tprivate currentPosition = 0;\n\tprivate targetPosition = 0;\n\tprivate currentTime = 0;\n\tprivate params: Partial<SpringParams> = {};\n\tprivate currentSolver: (t: seconds) => number;\n\tprivate getV: (t: seconds) => number;\n\tprivate getV2: (t: seconds) => number;\n\tprivate queueParams:\n\t\t| (Partial<SpringParams> & {\n\t\t\t\ttime: number;\n\t\t })\n\t\t| undefined;\n\tprivate queuePosition:\n\t\t| {\n\t\t\t\ttime: number;\n\t\t\t\tposition: number;\n\t\t }\n\t\t| undefined;\n\tconstructor(currentPosition = 0) {\n\t\tthis.targetPosition = currentPosition;\n\t\tthis.currentPosition = this.targetPosition;\n\t\tthis.currentSolver = () => this.targetPosition;\n\t\tthis.getV = () => 0;\n\t\tthis.getV2 = () => 0;\n\t}\n\tprivate resetSolver() {\n\t\tconst curV = this.getV(this.currentTime);\n\t\tthis.currentTime = 0;\n\t\tthis.currentSolver = solveSpring(\n\t\t\tthis.currentPosition,\n\t\t\tcurV,\n\t\t\tthis.targetPosition,\n\t\t\t0,\n\t\t\tthis.params,\n\t\t);\n\t\tthis.getV = getVelocity(this.currentSolver);\n\t\tthis.getV2 = getVelocity(this.getV);\n\t}\n\tarrived(): boolean {\n\t\treturn (\n\t\t\tMath.abs(this.targetPosition - this.currentPosition) < 0.01 &&\n\t\t\tthis.getV(this.currentTime) < 0.01 &&\n\t\t\tthis.getV2(this.currentTime) < 0.01 &&\n\t\t\tthis.queueParams === undefined &&\n\t\t\tthis.queuePosition === undefined\n\t\t);\n\t}\n\tsetPosition(targetPosition: number): void {\n\t\tthis.targetPosition = targetPosition;\n\t\tthis.currentPosition = targetPosition;\n\t\tthis.currentSolver = () => this.targetPosition;\n\t\tthis.getV = () => 0;\n\t\tthis.getV2 = () => 0;\n\t}\n\tupdate(delta = 0): void {\n\t\tthis.currentTime += delta;\n\t\tthis.currentPosition = this.currentSolver(this.currentTime);\n\t\tif (this.queueParams) {\n\t\t\tthis.queueParams.time -= delta;\n\t\t\tif (this.queueParams.time <= 0) {\n\t\t\t\tthis.updateParams({\n\t\t\t\t\t...this.queueParams,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tif (this.queuePosition) {\n\t\t\tthis.queuePosition.time -= delta;\n\t\t\tif (this.queuePosition.time <= 0) {\n\t\t\t\tthis.setTargetPosition(this.queuePosition.position);\n\t\t\t}\n\t\t}\n\t\tif (this.arrived()) {\n\t\t\tthis.setPosition(this.targetPosition);\n\t\t}\n\t}\n\tupdateParams(params: Partial<SpringParams>, delay = 0): void {\n\t\tif (delay > 0) {\n\t\t\tthis.queueParams = {\n\t\t\t\t...(this.queuePosition ?? {}),\n\t\t\t\t...params,\n\t\t\t\ttime: delay,\n\t\t\t};\n\t\t} else {\n\t\t\tthis.queuePosition = undefined;\n\t\t\tthis.params = {\n\t\t\t\t...this.params,\n\t\t\t\t...params,\n\t\t\t};\n\t\t\tthis.resetSolver();\n\t\t}\n\t}\n\tsetTargetPosition(targetPosition: number, delay = 0): void {\n\t\tif (delay > 0) {\n\t\t\tthis.queuePosition = {\n\t\t\t\t...(this.queuePosition ?? {}),\n\t\t\t\tposition: targetPosition,\n\t\t\t\ttime: delay,\n\t\t\t};\n\t\t} else {\n\t\t\tthis.queuePosition = undefined;\n\t\t\tthis.targetPosition = targetPosition;\n\t\t\tthis.resetSolver();\n\t\t}\n\t}\n\tgetCurrentPosition(): number {\n\t\treturn this.currentPosition;\n\t}\n}\n\nfunction solveSpring(\n\tfrom: number,\n\tvelocity: number,\n\tto: number,\n\tdelay: seconds = 0,\n\tparams?: Partial<SpringParams>,\n): (t: seconds) => number {\n\tconst soft = params?.soft ?? false;\n\tconst stiffness = params?.stiffness ?? 100;\n\tconst damping = params?.damping ?? 10;\n\tconst mass = params?.mass ?? 1;\n\tconst delta = to - from;\n\tif (soft || 1.0 <= damping / (2.0 * Math.sqrt(stiffness * mass))) {\n\t\tconst angular_frequency = -Math.sqrt(stiffness / mass);\n\t\tconst leftover = -angular_frequency * delta - velocity;\n\t\treturn (t: seconds) => {\n\t\t\tt -= delay;\n\t\t\tif (t < 0) return from;\n\t\t\treturn to - (delta + t * leftover) * Math.E ** (t * angular_frequency);\n\t\t};\n\t}\n\tconst damping_frequency = Math.sqrt(4.0 * mass * stiffness - damping ** 2.0);\n\tconst leftover =\n\t\t(damping * delta - 2.0 * mass * velocity) / damping_frequency;\n\tconst dfm = (0.5 * damping_frequency) / mass;\n\tconst dm = -(0.5 * damping) / mass;\n\treturn (t: seconds) => {\n\t\tt -= delay;\n\t\tif (t < 0) return from;\n\t\treturn (\n\t\t\tto -\n\t\t\t(Math.cos(t * dfm) * delta + Math.sin(t * dfm) * leftover) *\n\t\t\t\tMath.E ** (t * dm)\n\t\t);\n\t};\n}\n","import type { Disposable, HasElement } from \"#interfaces\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { measure } from \"#utils/schedule.ts\";\nimport { Spring } from \"#utils/spring.ts\";\nimport type { LyricPlayerBase } from \".\";\n\ninterface LineTransforms {\n\tposX: Spring;\n\tposY: Spring;\n}\n\nexport class BottomLineEl implements HasElement, Disposable {\n\tprivate element: HTMLElement = document.createElement(\"div\");\n\tprivate left = 0;\n\tprivate top = 0;\n\tprivate delay = 0;\n\t// 由 LyricPlayer 来设置\n\tlineSize: [number, number] = [0, 0];\n\treadonly lineTransforms: LineTransforms = {\n\t\tposX: new Spring(0),\n\t\tposY: new Spring(0),\n\t};\n\tprivate isFocused = false;\n\tprivate blur = 0;\n\tconstructor(private lyricPlayer: LyricPlayerBase) {\n\t\tthis.element.setAttribute(\n\t\t\t\"class\",\n\t\t\t`${styles.lyricLine} ${styles.bottomLine}`,\n\t\t);\n\t\tthis.element.dataset.bottomLine = \"true\";\n\t\tthis.rebuildStyle();\n\t}\n\tasync measureSize(): Promise<[number, number]> {\n\t\tconst size: [number, number] = await measure(() => [\n\t\t\tthis.element.clientWidth,\n\t\t\tthis.element.clientHeight,\n\t\t]);\n\t\treturn size;\n\t}\n\tprivate lastStyle = \"\";\n\tshow(): void {\n\t\tthis.rebuildStyle();\n\t}\n\thide(): void {\n\t\tthis.rebuildStyle();\n\t}\n\tsetFocused(focused: boolean): void {\n\t\tif (this.isFocused !== focused) {\n\t\t\tthis.isFocused = focused;\n\t\t\tif (focused) {\n\t\t\t\tthis.element.dataset.focused = \"true\";\n\t\t\t} else {\n\t\t\t\tdelete this.element.dataset.focused;\n\t\t\t}\n\t\t}\n\t}\n\tprivate rebuildStyle() {\n\t\tlet style = `transform:translate(${this.lineTransforms.posX\n\t\t\t.getCurrentPosition()\n\t\t\t.toFixed(2)}px,${this.lineTransforms.posY\n\t\t\t.getCurrentPosition()\n\t\t\t.toFixed(2)}px);`;\n\n\t\tif (!this.lyricPlayer.getEnableSpring() && this.isInSight) {\n\t\t\tstyle += `transition-delay:${this.delay}ms;`;\n\t\t}\n\n\t\tstyle += `filter:blur(${Math.min(5, this.blur)}px);`;\n\n\t\tif (style !== this.lastStyle) {\n\t\t\tthis.lastStyle = style;\n\t\t\tthis.element.setAttribute(\"style\", style);\n\t\t}\n\t}\n\tgetElement(): HTMLElement {\n\t\treturn this.element;\n\t}\n\tsetTransform(\n\t\tleft: number = this.left,\n\t\ttop: number = this.top,\n\t\tblur = 0,\n\t\tforce = false,\n\t\tdelay = 0,\n\t): void {\n\t\tthis.left = left;\n\t\tthis.top = top;\n\t\tthis.delay = (delay * 1000) | 0;\n\n\t\tif (force || !this.lyricPlayer.getEnableSpring()) {\n\t\t\tthis.blur = Math.min(32, blur);\n\t\t\tif (force) this.element.classList.add(styles.tmpDisableTransition);\n\t\t\tthis.lineTransforms.posX.setPosition(left);\n\t\t\tthis.lineTransforms.posY.setPosition(top);\n\t\t\tif (!this.lyricPlayer.getEnableSpring()) this.show();\n\t\t\telse this.rebuildStyle();\n\t\t\tif (force)\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tthis.element.classList.remove(styles.tmpDisableTransition);\n\t\t\t\t});\n\t\t} else {\n\t\t\tthis.blur = Math.min(5, blur);\n\t\t\tthis.lineTransforms.posX.setTargetPosition(left, delay);\n\t\t\tthis.lineTransforms.posY.setTargetPosition(top, delay);\n\t\t}\n\t}\n\tupdate(delta = 0): void {\n\t\tif (!this.lyricPlayer.getEnableSpring()) return;\n\t\tthis.lineTransforms.posX.update(delta);\n\t\tthis.lineTransforms.posY.update(delta);\n\t\tif (this.isInSight) {\n\t\t\tthis.show();\n\t\t} else {\n\t\t\tthis.hide();\n\t\t}\n\t}\n\tget isInSight(): boolean {\n\t\tconst l = this.lineTransforms.posX.getCurrentPosition();\n\t\tconst t = this.lineTransforms.posY.getCurrentPosition();\n\t\tconst r = l + this.lineSize[0];\n\t\tconst b = t + this.lineSize[1];\n\t\tconst pr = this.lyricPlayer.size[0];\n\t\tconst pb = this.lyricPlayer.size[1];\n\t\treturn !(l > pr || t > pb || r < 0 || b < 0);\n\t}\n\tdispose(): void {\n\t\tthis.element.remove();\n\t}\n}\n","type ValueOf<T extends Record<PropertyKey, unknown>> = T[keyof T];\n\n/** 歌词中不雅用语的掩码模式 */\nexport const MaskObsceneWordsMode = {\n\t/** 禁用任何不雅用语掩码 */\n\tDisabled: \"\",\n\t/** 完全掩码所有不雅用语 */\n\tFullMask: \"full-mask\",\n\t/** 保留首尾字符,屏蔽中间字符 */\n\tPartialMask: \"partial-mask\",\n} as const;\n\n/** 歌词中不雅用语的掩码模式枚举类型,见 {@link MaskObsceneWordsMode} */\nexport type MaskObsceneWordsMode = ValueOf<typeof MaskObsceneWordsMode>;\n\n/**\n * 歌词行的渲染模式\n * @internal\n */\nexport const LyricLineRenderMode = {\n\tSOLID: 0,\n\tGRADIENT: 1,\n} as const;\n\n/**\n * 歌词行的渲染模式枚举类型,见 {@link LyricLineRenderMode}\n * @internal\n */\nexport type LyricLineRenderMode = ValueOf<typeof LyricLineRenderMode>;\n\n/** 布局对齐锚点 */\nexport const LayoutAlignAnchor = {\n\tTop: \"top\",\n\tCenter: \"center\",\n\tBottom: \"bottom\",\n} as const;\n\n/** 布局对齐锚点枚举类型,见 {@link LayoutAlignAnchor} */\nexport type LayoutAlignAnchor = ValueOf<typeof LayoutAlignAnchor>;\n","import { clamp } from \"#utils/clamp.ts\";\nimport type { SpringParams } from \"#utils/spring.ts\";\nimport type { LayoutAlignAnchor } from \"./consts.ts\";\nimport type { LyricLineGroupBase } from \"./group.ts\";\nimport type { PlayerTimelineState } from \"./timeline.ts\";\n\n/**\n * 播放器布局状态。\n *\n * 这部分状态保存布局计算阶段所需的配置项与缓存值,\n * 例如对齐方式、间奏点尺寸、上一轮布局命中的目标行等。\n * 不描述播放时间线或用户滚动交互,仅记录当前歌词排布。\n */\nexport interface PlayerLayoutState {\n\t/** 间奏点元素当前测量得到的尺寸 */\n\tinterludeDotsSize: [number, number];\n\t/** 上一轮布局实际对齐的目标歌词行索引 */\n\ttargetAlignIndex: number;\n\t/** 上一轮布局时是否处于间奏区间 */\n\tlastInterludeState: boolean;\n\t/** 当前歌词目标行的对齐锚点 */\n\talignAnchor: LayoutAlignAnchor;\n\t/** 当前歌词目标行在播放器高度中的相对对齐位置 */\n\talignPosition: number;\n\t/** 视口上下额外保留的预渲染距离,单位为像素 */\n\toverscanPx: number;\n}\n\n/**\n * 当前命中的间奏区间信息。\n *\n * 当播放器检测到当前时间处于两句歌词之间的较长空档期时,\n * 会生成该结构,用于驱动间奏点动画的显示位置与时间范围。\n */\nexport interface PlayerInterlude {\n\t/** 间奏动画的开始时间 */\n\tstartTime: number;\n\t/** 间奏动画的结束时间 */\n\tendTime: number;\n\t/** 间奏点应插入到哪一行之后;`-1` 表示位于第一行之前 */\n\tanchorLineIndex: number;\n\t/** 间奏结束后的下一句是否为对唱歌词 */\n\tisNextDuet: boolean;\n}\n\n/** {@link computeCurrentInterlude} 的参数类型 */\nexport interface ComputeCurrentInterludeInput {\n\tcurrentTime: number;\n\tscrollToIndex: number;\n\tcurrentGroups: LyricLineGroupBase[];\n}\n\n/**\n * 根据当前时间与当前目标行,计算当前是否处于某个可展示的间奏区间。\n *\n * 仅识别时间轴上的间奏空档,不涉及具体 DOM 元素的创建与摆放。\n * 若当前不应展示间奏动画,则返回 `undefined`。\n */\nexport function computeCurrentInterlude(\n\tinput: ComputeCurrentInterludeInput,\n): PlayerInterlude | undefined {\n\tconst currentTime = input.currentTime + 20;\n\tconst currentIndex = input.scrollToIndex;\n\tconst groups = input.currentGroups;\n\n\tconst checkGap = (k: number): PlayerInterlude | undefined => {\n\t\tif (k < -1 || k >= groups.length - 1) return undefined;\n\n\t\tconst prevGroup = k === -1 ? null : groups[k];\n\t\tconst nextGroup = groups[k + 1];\n\n\t\tconst gapStart = prevGroup ? prevGroup.endTime : 0;\n\t\tconst gapEnd = Math.max(gapStart, nextGroup.startTime - 250);\n\n\t\tif (gapEnd - gapStart < 4000) return undefined;\n\n\t\tif (gapEnd > currentTime && gapStart < currentTime) {\n\t\t\treturn {\n\t\t\t\tstartTime: Math.max(gapStart, currentTime),\n\t\t\t\tendTime: gapEnd,\n\t\t\t\tanchorLineIndex: k,\n\t\t\t\tisNextDuet: nextGroup.mainLine.getLine().isDuet,\n\t\t\t};\n\t\t}\n\t\treturn undefined;\n\t};\n\n\treturn (\n\t\tcheckGap(currentIndex - 1) ||\n\t\tcheckGap(currentIndex) ||\n\t\tcheckGap(currentIndex + 1)\n\t);\n}\n\n/**\n * {@link computeLinePosYSpringParams} 的参数类型,\n * 用于决定当前歌词纵向滚动动画的弹簧参数。\n */\nexport interface ComputeLinePosYSpringParamsInput {\n\t/** 是否启用弹簧动画 */\n\tenabled: boolean;\n\t/** 当前用于布局的歌词数据 */\n\tcurrentGroups: LyricLineGroupBase[];\n\t/** 当前目标对齐行索引 */\n\tscrollToIndex: number;\n\t/** 是否处于 seeking 模式 */\n\tisSeeking: boolean;\n\t/** 是否处于间奏区间 */\n\tisInterludeActive: boolean;\n}\n\n/** {@link computeLinePosYSpringParams} 的结果类型 */\nexport interface ComputeLinePosYSpringParamsResult {\n\t/** 是否需要更新纵向弹簧参数 */\n\tshouldUpdate: boolean;\n\t/** 若需要更新,则返回新的参数 */\n\tparams?: Partial<SpringParams>;\n}\n\n/**\n * 根据当前播放上下文计算歌词纵向滚动动画的弹簧参数。\n *\n * 其策略为:\n * - seeking 或间奏时使用更稳定的固定参数\n * - 普通播放时根据相邻歌词的时间间隔动态调整 stiffness / damping\n */\nexport function computeLinePosYSpringParams(\n\tinput: ComputeLinePosYSpringParamsInput,\n): ComputeLinePosYSpringParamsResult {\n\tconst {\n\t\tenabled,\n\t\tcurrentGroups,\n\t\tscrollToIndex,\n\t\tisSeeking,\n\t\tisInterludeActive,\n\t} = input;\n\n\tif (!enabled || currentGroups.length === 0) {\n\t\treturn { shouldUpdate: false };\n\t}\n\n\tif (isSeeking || isInterludeActive) {\n\t\treturn {\n\t\t\tshouldUpdate: true,\n\t\t\tparams: { stiffness: 90, damping: 15 },\n\t\t};\n\t}\n\n\tconst currentGroup = currentGroups[scrollToIndex];\n\tconst prevGroup = currentGroups[scrollToIndex - 1];\n\n\tif (!currentGroup || !prevGroup) {\n\t\treturn { shouldUpdate: false };\n\t}\n\n\tconst interval = currentGroup.startTime - prevGroup.startTime;\n\n\tconst MIN_INTERVAL = 100;\n\tconst MAX_INTERVAL = 800;\n\tconst clampedInterval = clamp(interval, MIN_INTERVAL, MAX_INTERVAL);\n\n\tconst MAX_STIFFNESS = 220;\n\tconst MIN_STIFFNESS = 170;\n\n\tlet ratio =\n\t\t1 - (clampedInterval - MIN_INTERVAL) / (MAX_INTERVAL - MIN_INTERVAL);\n\n\tratio = ratio ** 0.2;\n\n\tconst targetStiffness =\n\t\tMIN_STIFFNESS + ratio * (MAX_STIFFNESS - MIN_STIFFNESS);\n\n\tconst dampingMultiplier = 2.2;\n\tconst targetDamping = Math.sqrt(targetStiffness) * dampingMultiplier;\n\n\treturn {\n\t\tshouldUpdate: true,\n\t\tparams: {\n\t\t\tstiffness: targetStiffness,\n\t\t\tdamping: targetDamping,\n\t\t},\n\t};\n}\n\n/**\n * {@link computeGroupPresentation} 的参数类型。\n *\n * 描述一行歌词在当前布局上下文中的全部关键信息,\n * 用于计算其视觉呈现结果。\n */\nexport interface ComputeGroupPresentationInput {\n\t/** 当前歌词组索引 */\n\tgroupIndex: number;\n\t/** 当前目标对齐行索引 */\n\tscrollToIndex: number;\n\t/** 当前缓冲区({@link PlayerTimelineState.bufferedGroups})中最靠后的歌词行索引 */\n\tlatestIndex: number;\n\t/** 当前歌词行是否在缓冲集合内 */\n\thasBuffered: boolean;\n\t/** 是否启用隐藏已播放行 */\n\thidePassedLines: boolean;\n\t/** 是否处于播放状态 */\n\tisPlaying: boolean;\n\t/** 当前歌词是否为非逐词歌词 */\n\tisNonDynamic: boolean;\n\t/** 是否启用模糊效果 */\n\tenableBlur: boolean;\n\t/** 是否正在进行滚动交互 */\n\tisUserScrolling: boolean;\n\t/** 是否处于紧凑布局环境,例如窄屏 */\n\tisCompact: boolean;\n\t/** 当前命中的间奏区间信息 */\n\tinterlude?: PlayerInterlude;\n}\n\n/** {@link computeGroupPresentation} 的结果类型 */\nexport interface ComputeGroupPresentationResult {\n\t/** 当前歌词行是否应视为活跃行 */\n\tisActive: boolean;\n\t/** 当前歌词行的目标不透明度 */\n\ttargetOpacity: number;\n\t/** 当前歌词行的目标模糊值 */\n\tblurLevel: number;\n}\n\n/**\n * 计算一组歌词在当前布局中的视觉呈现参数。\n *\n * 根据播放状态、缓冲状态、布局模式与间奏信息,\n * 生成一组歌词最终应使用的活跃状态、不透明度与模糊值。\n */\nexport function computeGroupPresentation(\n\tinput: ComputeGroupPresentationInput,\n): ComputeGroupPresentationResult {\n\tconst {\n\t\tgroupIndex,\n\t\tscrollToIndex,\n\t\tlatestIndex,\n\t\thasBuffered,\n\t\thidePassedLines,\n\t\tisPlaying,\n\t\tisNonDynamic,\n\t\tenableBlur,\n\t\tisUserScrolling,\n\t\tisCompact,\n\t\tinterlude,\n\t} = input;\n\n\tconst isActive =\n\t\thasBuffered || (groupIndex >= scrollToIndex && groupIndex < latestIndex);\n\n\tconst blurLevel = computeLineBlur({\n\t\tenableBlur,\n\t\tisUserScrolling,\n\t\tisActive,\n\t\titemIndex: groupIndex,\n\t\tscrollToIndex,\n\t\tlatestIndex,\n\t\tisCompact,\n\t});\n\n\tlet targetOpacity: number;\n\tif (hidePassedLines) {\n\t\tif (\n\t\t\tgroupIndex <\n\t\t\t\t(interlude ? interlude.anchorLineIndex + 1 : scrollToIndex) &&\n\t\t\tisPlaying\n\t\t) {\n\t\t\t// 为了避免浏览器优化,这里使用了一个极小但不为零的值(几乎不可见)\n\t\t\ttargetOpacity = 1e-4;\n\t\t} else if (hasBuffered) {\n\t\t\ttargetOpacity = 0.85;\n\t\t} else {\n\t\t\ttargetOpacity = isNonDynamic ? 0.2 : 1;\n\t\t}\n\t} else if (hasBuffered) {\n\t\ttargetOpacity = 0.85;\n\t} else {\n\t\ttargetOpacity = isNonDynamic ? 0.2 : 1;\n\t}\n\n\treturn { isActive, targetOpacity, blurLevel };\n}\n\n/** {@link computeLineBlur} 的参数类型 */\nexport interface ComputeLineBlurInput {\n\t/** 是否启用了模糊效果 */\n\tenableBlur: boolean;\n\t/** 用户是否正在滚动 */\n\tisUserScrolling: boolean;\n\t/** 当前项是否活跃 */\n\tisActive: boolean;\n\t/** 当前项索引 */\n\titemIndex: number;\n\t/** 当前目标对齐行索引 */\n\tscrollToIndex: number;\n\t/** 缓冲区中最靠后的歌词行索引 */\n\tlatestIndex: number;\n\t/** 是否处于紧凑布局环境,例如窄屏 */\n\tisCompact: boolean;\n}\n\n/**\n * 计算一行歌词在当前布局中的模糊等级。\n *\n * 越远离当前对齐区域的歌词会得到更高的模糊值;\n * 活跃行、滚动交互中或关闭模糊效果时返回 `0`。\n */\nexport function computeLineBlur(input: ComputeLineBlurInput): number {\n\tconst {\n\t\tenableBlur,\n\t\tisUserScrolling,\n\t\tisActive,\n\t\titemIndex,\n\t\tscrollToIndex,\n\t\tlatestIndex,\n\t\tisCompact,\n\t} = input;\n\n\tif (!enableBlur || isUserScrolling || isActive) {\n\t\treturn 0;\n\t}\n\n\tlet blurLevel = 1;\n\n\tif (itemIndex < scrollToIndex) {\n\t\tblurLevel += Math.abs(scrollToIndex - itemIndex) + 1;\n\t} else {\n\t\tblurLevel += Math.abs(itemIndex - Math.max(scrollToIndex, latestIndex));\n\t}\n\n\treturn isCompact ? blurLevel * 0.8 : blurLevel;\n}\n","import { clamp } from \"#utils/clamp.ts\";\n\n/**\n * 播放器滚动状态。\n *\n * 这部分状态描述用户手势/滚轮滚动产生的临时偏移,以及当前允许滚动的范围。\n * 改状态仅记录用户如何把当前视图上下拖动,不决定应该滚动到哪一行,\n * 后者由时间线状态与布局计算共同决定。\n */\nexport interface PlayerScrollState {\n\t/** 允许的滚动偏移范围 */\n\tscrollBoundary: {\n\t\t/** 允许的最小偏移量 */\n\t\tminOffset: number;\n\t\t/** 允许的最大偏移量 */\n\t\tmaxOffset: number;\n\t};\n\t/** 当前用户滚动带来的额外偏移量 */\n\tscrollOffset: number;\n\t/** 是否允许用户通过手势或滚轮滚动歌词视图 */\n\tallowScroll: boolean;\n\t/** 是否处于用户滚动过,尚未回归自动对齐的状态 */\n\tisScrolled: boolean;\n\t/** 是否正在进行滚动交互或惯性滚动 */\n\tisUserScrolling: boolean;\n}\n\n/**\n * 将滚动偏移量限制在当前允许的滚动边界内。\n *\n * 当手势滚动、滚轮滚动或惯性滚动更新了 {@link PlayerScrollState.scrollOffset}\n * 后,应调用本函数以避免视图越界。\n */\nexport function clampPlayerScrollOffset(scrollState: PlayerScrollState): void {\n\tscrollState.scrollOffset = clamp(\n\t\tscrollState.scrollOffset,\n\t\tscrollState.scrollBoundary.minOffset,\n\t\tscrollState.scrollBoundary.maxOffset,\n\t);\n}\n\n/**\n * 重置滚动状态到未发生用户滚动时的初始状态。\n *\n * 本函数会清除当前偏移,并结束“已滚动”与“正在滚动”的标记;\n * **不会清理**外部持有的计时器或事件监听器。\n */\nexport function resetPlayerScrollState(scrollState: PlayerScrollState): void {\n\tscrollState.isScrolled = false;\n\tscrollState.scrollOffset = 0;\n\tscrollState.isUserScrolling = false;\n}\n\n/**\n * {@link attachPlayerScrollHandlers} 所需的宿主回调。\n *\n * 这些回调将滚动模块与具体播放器实现解耦:\n * 滚动模块只负责处理输入事件和更新滚动状态,布局刷新、点击转发等副作用\n * 由宿主决定如何执行。\n */\nexport interface AttachPlayerScrollHandlersCallbacks {\n\t/** 开始一次滚动处理前调用,返回 `false` 可阻止本次滚动 */\n\tonBeginScroll: () => boolean;\n\t/** 一次滚动交互或惯性滚动结束时调用 */\n\tonEndScroll: () => void;\n\t/** 请求宿主重新布局 */\n\tonLayout: (sync: boolean, force: boolean) => void;\n\t/** 判断某个点击目标是否仍属于当前播放器视图 */\n\tcontainsTarget: (target: Node) => boolean;\n\t/** 将点击事件转发给命中的目标元素 */\n\tclickTarget: (target: HTMLElement) => void;\n}\n\n/**\n * 向指定元素挂载歌词滚动相关的交互处理器。\n *\n * 该函数会处理:\n * - 触摸拖拽滚动\n * - 触摸结束后的惯性滚动\n * - 滚轮滚动\n * - 轻触时的点击透传\n *\n * 只更新 {@link PlayerScrollState} 并通过回调通知宿主执行布局或其它副作用,\n * 不直接依赖具体的播放器类实现。\n */\nexport function attachPlayerScrollHandlers(\n\telement: HTMLElement,\n\tscrollState: PlayerScrollState,\n\tcallbacks: AttachPlayerScrollHandlersCallbacks,\n): void {\n\tlet startScrollY = 0;\n\n\tlet startTouchPosY = 0;\n\tlet startTouchStartX = 0;\n\tlet startTouchStartY = 0;\n\n\tlet lastMoveY = 0;\n\tlet startScrollTime = 0;\n\tlet scrollSpeed = 0;\n\tlet curScrollId = 0;\n\n\telement.addEventListener(\"touchstart\", (evt) => {\n\t\tif (callbacks.onBeginScroll()) {\n\t\t\tscrollState.isUserScrolling = true;\n\n\t\t\tevt.preventDefault();\n\t\t\tstartScrollY = scrollState.scrollOffset;\n\n\t\t\tstartTouchPosY = evt.touches[0].screenY;\n\t\t\tlastMoveY = startTouchPosY;\n\n\t\t\tstartTouchStartX = evt.touches[0].screenX;\n\t\t\tstartTouchStartY = evt.touches[0].screenY;\n\n\t\t\tstartScrollTime = Date.now();\n\t\t\tscrollSpeed = 0;\n\n\t\t\tcallbacks.onLayout(true, true);\n\t\t}\n\t});\n\n\telement.addEventListener(\"touchmove\", (evt) => {\n\t\tif (callbacks.onBeginScroll()) {\n\t\t\tevt.preventDefault();\n\t\t\tconst currentY = evt.touches[0].screenY;\n\n\t\t\tconst deltaY = currentY - startTouchPosY;\n\t\t\tscrollState.scrollOffset = startScrollY - deltaY;\n\t\t\tclampPlayerScrollOffset(scrollState);\n\n\t\t\tconst now = Date.now();\n\t\t\tconst dt = now - startScrollTime;\n\t\t\tif (dt > 0) {\n\t\t\t\tscrollSpeed = (currentY - lastMoveY) / dt;\n\t\t\t}\n\t\t\tlastMoveY = currentY;\n\t\t\tstartScrollTime = now;\n\n\t\t\tcallbacks.onLayout(true, true);\n\t\t}\n\t});\n\n\telement.addEventListener(\"touchend\", (evt) => {\n\t\tif (callbacks.onBeginScroll()) {\n\t\t\tevt.preventDefault();\n\n\t\t\tconst touch = evt.changedTouches[0];\n\t\t\tconst moveX = Math.abs(touch.screenX - startTouchStartX);\n\t\t\tconst moveY = Math.abs(touch.screenY - startTouchStartY);\n\n\t\t\tif (moveX < 10 && moveY < 10) {\n\t\t\t\tconst target = document.elementFromPoint(touch.clientX, touch.clientY);\n\t\t\t\tif (target instanceof HTMLElement && callbacks.containsTarget(target)) {\n\t\t\t\t\tcallbacks.clickTarget(target);\n\t\t\t\t}\n\t\t\t\tscrollState.isUserScrolling = false;\n\t\t\t\tcallbacks.onEndScroll();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tstartTouchPosY = 0;\n\t\t\tconst scrollId = ++curScrollId;\n\n\t\t\tif (Math.abs(scrollSpeed) < 0.1) scrollSpeed = 0;\n\n\t\t\tlet lastFrameTime = performance.now();\n\n\t\t\tconst onScrollFrame = (time: number) => {\n\t\t\t\tif (scrollId !== curScrollId) return;\n\n\t\t\t\tconst dt = time - lastFrameTime;\n\t\t\t\tlastFrameTime = time;\n\n\t\t\t\tif (dt <= 0 || dt > 100) {\n\t\t\t\t\trequestAnimationFrame(onScrollFrame);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (Math.abs(scrollSpeed) > 0.05) {\n\t\t\t\t\tscrollState.scrollOffset -= scrollSpeed * dt;\n\n\t\t\t\t\tclampPlayerScrollOffset(scrollState);\n\n\t\t\t\t\tconst frictionFactor = 0.95 ** (dt / 16);\n\t\t\t\t\tscrollSpeed *= frictionFactor;\n\n\t\t\t\t\tcallbacks.onLayout(true, true);\n\n\t\t\t\t\trequestAnimationFrame(onScrollFrame);\n\t\t\t\t} else {\n\t\t\t\t\tscrollState.isUserScrolling = false;\n\t\t\t\t\tcallbacks.onEndScroll();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\trequestAnimationFrame(onScrollFrame);\n\t\t} else {\n\t\t\tscrollState.isUserScrolling = false;\n\t\t}\n\t});\n\n\telement.addEventListener(\n\t\t\"wheel\",\n\t\t(evt) => {\n\t\t\tif (callbacks.onBeginScroll()) {\n\t\t\t\tevt.preventDefault();\n\n\t\t\t\tif (evt.deltaMode === evt.DOM_DELTA_PIXEL) {\n\t\t\t\t\tscrollState.scrollOffset += evt.deltaY;\n\t\t\t\t\tclampPlayerScrollOffset(scrollState);\n\t\t\t\t\tcallbacks.onLayout(true, false);\n\t\t\t\t} else {\n\t\t\t\t\tscrollState.scrollOffset += evt.deltaY * 50;\n\t\t\t\t\tclampPlayerScrollOffset(scrollState);\n\t\t\t\t\tcallbacks.onLayout(false, false);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{ passive: false },\n\t);\n}\n","export const eqSet: <T>(xs: Set<T>, ys: Set<T>) => boolean = (\n\txs,\n\tys,\n): boolean => xs.size === ys.size && [...xs].every((x) => ys.has(x));\n","import { eqSet } from \"#utils/eq-set.ts\";\nimport type { LyricLineGroupBase } from \"./group.ts\";\n\n/**\n * 播放时间线状态。\n *\n * 描述播放器在时间轴上的当前位置,当前处于激活状态的歌词组信息\n */\nexport interface PlayerTimelineState {\n\t/** 当前播放时间,单位为毫秒 */\n\tcurrentTime: number;\n\t/** 上一次提交到时间线状态的播放时间,单位为毫秒 */\n\tlastCurrentTime: number;\n\t/** 热行:当前时间 {@link currentTime} 正在命中的组(含主行+可能的背景行) */\n\thotGroups: Set<number>;\n\t/** 缓冲组:UI 上还保持激活表现的组索引,通常包含热组,和刚结束仍在过渡中的组 */\n\tbufferedGroups: Set<number>;\n\t/** 当前应滚动对齐到的歌词组索引 */\n\tscrollToIndex: number;\n\t/** 是否正在拖拽进度条。若是,更新时丢弃缓冲行,并根据当前时间直接计算热行 */\n\tisSeeking: boolean;\n\t/** 是否处于播放状态 */\n\tisPlaying: boolean;\n\t/** 是否已经完成至少一次初始布局 */\n\tinitialLayoutFinished: boolean;\n}\n\n/** {@link computePlayerTimeState} 的参数类型 */\nexport interface ComputePlayerTimeStateInput {\n\ttime: number;\n\tcurrentGroups: LyricLineGroupBase[];\n\ttimelineState: Readonly<PlayerTimelineState>;\n}\n\n/** {@link computePlayerTimeState} 的返回类型 */\nexport interface ComputePlayerTimeStateResult {\n\t/** 计算后的新热组集合 */\n\tnextHotGroups: Set<number>;\n\t/** 需要新加入热组集合的组索引 */\n\taddedIds: Set<number>;\n\t/** 需要从热组集合中移除的组索引 */\n\tremovedHotIds: Set<number>;\n\t/** 需要从缓冲组集合中移除的组索引 */\n\tremovedBufferedIds: Set<number>;\n}\n\n/**\n * 计算指定时间点的热行/缓冲行状态转移的纯函数。其行为包括:\n *\n * - 根据当前时间和已有的热行状态,计算出新的热行状态,并返回应新增的热行 ID 和应移除的热行 ID\n * - 根据新的热行状态和已有的缓冲行状态,计算出应移除的缓冲行 ID\n */\nexport function computePlayerTimeState(\n\tinput: ComputePlayerTimeStateInput,\n): ComputePlayerTimeStateResult {\n\tconst {\n\t\ttime,\n\t\tcurrentGroups,\n\t\ttimelineState: { hotGroups, bufferedGroups },\n\t} = input;\n\n\tconst nextHotGroups = new Set(hotGroups);\n\tconst addedIds = new Set<number>();\n\tconst removedHotIds = new Set<number>();\n\tconst removedBufferedIds = new Set<number>();\n\n\tfor (const lastHotId of hotGroups) {\n\t\tconst group = currentGroups[lastHotId];\n\t\tif (!group || time < group.startTime || group.endTime <= time) {\n\t\t\tnextHotGroups.delete(lastHotId);\n\t\t\tremovedHotIds.add(lastHotId);\n\t\t}\n\t}\n\n\tfor (let id = 0; id < currentGroups.length; id++) {\n\t\tconst group = currentGroups[id];\n\t\tif (!group) continue;\n\n\t\tif (\n\t\t\tgroup.startTime <= time &&\n\t\t\tgroup.endTime > time &&\n\t\t\t!nextHotGroups.has(id)\n\t\t) {\n\t\t\tnextHotGroups.add(id);\n\t\t\taddedIds.add(id);\n\t\t}\n\t}\n\n\tfor (const id of bufferedGroups) {\n\t\tif (!nextHotGroups.has(id)) {\n\t\t\tremovedBufferedIds.add(id);\n\t\t}\n\t}\n\n\treturn {\n\t\tnextHotGroups,\n\t\taddedIds,\n\t\tremovedHotIds,\n\t\tremovedBufferedIds,\n\t};\n}\n\n/**\n * 在 seeking 场景下,根据当前时间选出应对齐滚动到的目标行索引。\n *\n * 若当前仍存在缓冲行,则优先对齐到最靠前的缓冲行;\n * 否则对齐到第一条开始时间不小于当前时间的歌词行。\n */\nexport function pickScrollToIndexForSeek(\n\ttime: number,\n\tcurrentGroups: LyricLineGroupBase[],\n\tbufferedGroups: ReadonlySet<number>,\n): number {\n\tif (bufferedGroups.size > 0) {\n\t\treturn Math.min(...bufferedGroups);\n\t}\n\tconst foundIndex = currentGroups.findIndex(\n\t\t(group) => group.startTime >= time,\n\t);\n\treturn foundIndex === -1 ? currentGroups.length : foundIndex;\n}\n\n/**\n * {@link commitPlayerTimeState} 的参数类型。\n *\n * 用于将一次时间线状态转移提交回 {@link PlayerTimelineState},\n * 并生成供宿主执行的副作用应用计划。\n */\nexport interface CommitPlayerTimeStateInput {\n\t/** 要被更新的时间线状态对象 */\n\ttimelineState: PlayerTimelineState;\n\t/** 当前播放时间,单位为毫秒 */\n\ttime: number;\n\t/** 当前用于计算的歌词数据 */\n\tcurrentGroups: LyricLineGroupBase[];\n\t/** 底部附加区域当前是否有可见内容 */\n\thasBottomContent: boolean;\n\t/** 由 {@link computePlayerTimeState} 得到的状态转移结果 */\n\tstateResult: ComputePlayerTimeStateResult;\n}\n\n/** {@link commitPlayerTimeState} 的返回类型 */\nexport interface CommitPlayerTimeStateResult {\n\t/** 提交后是否需要重新布局 */\n\tshouldLayout: boolean;\n\t/** 提交后是否需要重置用户滚动状态 */\n\tshouldResetScroll: boolean;\n\t/** 需要启用的歌词组索引列表 */\n\tgroupsToEnable: number[];\n\t/** 需要禁用的歌词组索引列表 */\n\tgroupsToDisable: number[];\n}\n\n/**\n * 提交时间线状态转移的纯函数。\n *\n * 把一次时间线状态转移写回 {@link PlayerTimelineState},\n * 并返回一份供宿主执行的副作用应用计划,例如启用/禁用哪些歌词行、\n * 是否需要重置用户滚动状态、是否需要触发布局。\n */\nexport function commitPlayerTimeState(\n\tinput: CommitPlayerTimeStateInput,\n): CommitPlayerTimeStateResult {\n\tconst { timelineState, time, currentGroups, hasBottomContent, stateResult } =\n\t\tinput;\n\tconst { addedIds, removedHotIds, removedBufferedIds } = stateResult;\n\tconst { isSeeking } = timelineState;\n\n\ttimelineState.currentTime = time;\n\ttimelineState.hotGroups = stateResult.nextHotGroups;\n\n\tlet shouldLayout = false;\n\tlet shouldResetScroll = false;\n\tconst groupsToEnable: number[] = [];\n\tconst groupsToDisable = new Set<number>();\n\n\tif (isSeeking) {\n\t\ttimelineState.bufferedGroups = new Set([...timelineState.hotGroups]);\n\t\ttimelineState.scrollToIndex = pickScrollToIndexForSeek(\n\t\t\ttime,\n\t\t\tcurrentGroups,\n\t\t\ttimelineState.bufferedGroups,\n\t\t);\n\t\tfor (const id of removedHotIds) groupsToDisable.add(id);\n\t\tfor (const id of timelineState.hotGroups) groupsToEnable.push(id);\n\t\tfor (const id of removedBufferedIds) groupsToDisable.add(id);\n\n\t\tshouldResetScroll = true;\n\t\tshouldLayout = true;\n\t} else if (addedIds.size > 0) {\n\t\tfor (const id of addedIds) {\n\t\t\ttimelineState.bufferedGroups.add(id);\n\t\t\tgroupsToEnable.push(id);\n\t\t}\n\t\tfor (const id of removedBufferedIds) {\n\t\t\ttimelineState.bufferedGroups.delete(id);\n\t\t\tgroupsToDisable.add(id);\n\t\t}\n\t\tif (timelineState.bufferedGroups.size > 0) {\n\t\t\ttimelineState.scrollToIndex = Math.min(...timelineState.bufferedGroups);\n\t\t}\n\t\tshouldLayout = true;\n\t} else if (\n\t\tremovedBufferedIds.size > 0 &&\n\t\teqSet(removedBufferedIds, timelineState.bufferedGroups)\n\t) {\n\t\tfor (const id of timelineState.bufferedGroups) {\n\t\t\tif (timelineState.hotGroups.has(id)) continue;\n\t\t\ttimelineState.bufferedGroups.delete(id);\n\t\t\tgroupsToDisable.add(id);\n\t\t}\n\t\tshouldLayout = true;\n\t}\n\n\tif (timelineState.bufferedGroups.size === 0 && currentGroups.length > 0) {\n\t\tconst lastGroup = currentGroups[currentGroups.length - 1];\n\t\tif (time >= lastGroup.endTime) {\n\t\t\tconst targetIndex = hasBottomContent\n\t\t\t\t? currentGroups.length\n\t\t\t\t: currentGroups.length - 1;\n\t\t\tif (timelineState.scrollToIndex !== targetIndex) {\n\t\t\t\ttimelineState.scrollToIndex = targetIndex;\n\t\t\t\tshouldLayout = true;\n\t\t\t}\n\t\t}\n\t}\n\n\ttimelineState.lastCurrentTime = time;\n\n\treturn {\n\t\tshouldLayout,\n\t\tshouldResetScroll,\n\t\tgroupsToEnable,\n\t\tgroupsToDisable: [...groupsToDisable],\n\t};\n}\n","import structuredClone from \"@ungap/structured-clone\";\nimport type {\n\tDisposable,\n\tHasElement,\n\tLyricLine,\n\tLyricWord,\n\tOptimizeLyricOptions,\n} from \"#interfaces\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { clampPositive } from \"#utils/clamp.ts\";\nimport { optimizeLyricLines } from \"#utils/optimize-lyric.ts\";\nimport type { SpringParams } from \"#utils/spring.ts\";\nimport { InterludeDots } from \"../dom/interlude-dots.ts\";\nimport { BottomLineEl } from \"./bottom-line.ts\";\nimport { LayoutAlignAnchor, MaskObsceneWordsMode } from \"./consts.ts\";\nimport type { LyricLineGroupBase } from \"./group.ts\";\nimport {\n\tcomputeCurrentInterlude,\n\tcomputeGroupPresentation,\n\tcomputeLineBlur,\n\tcomputeLinePosYSpringParams,\n\ttype PlayerLayoutState,\n} from \"./layout.ts\";\nimport type { LyricLineBase } from \"./line.ts\";\nimport {\n\tattachPlayerScrollHandlers,\n\ttype PlayerScrollState,\n\tresetPlayerScrollState,\n} from \"./scroll.ts\";\nimport {\n\tcommitPlayerTimeState,\n\tcomputePlayerTimeState,\n\ttype PlayerTimelineState,\n} from \"./timeline.ts\";\n\nexport type { PlayerLayoutState } from \"./layout.ts\";\nexport type { LyricLineBase } from \"./line.ts\";\nexport type { PlayerScrollState } from \"./scroll.ts\";\nexport type { PlayerTimelineState } from \"./timeline.ts\";\n\n/**\n * 歌词播放器的基类,已经包含了有关歌词操作和排版的功能,\n * 子类需要为其实现对应的显示展示操作\n */\nexport abstract class LyricPlayerBase\n\textends EventTarget\n\timplements HasElement, Disposable\n{\n\tprotected element: HTMLElement = document.createElement(\"div\");\n\tabstract get baseFontSize(): number;\n\n\t/** 播放时间线状态 */\n\tprotected timelineState: PlayerTimelineState = {\n\t\tcurrentTime: 0,\n\t\tlastCurrentTime: 0,\n\t\thotGroups: new Set(),\n\t\tbufferedGroups: new Set(),\n\t\tscrollToIndex: 0,\n\t\tisSeeking: false,\n\t\tisPlaying: true,\n\t\tinitialLayoutFinished: false,\n\t};\n\t/** @internal */\n\tlyricGroupElementMap: WeakMap<Element, LyricLineGroupBase> = new WeakMap();\n\tprotected currentLyricLines: LyricLine[] = [];\n\tprotected processedLines: LyricLine[] = [];\n\tprotected lyricLinesIndexes: WeakMap<LyricLineBase, number> = new WeakMap();\n\tprotected isNonDynamic = false;\n\tprotected hasDuetLine = false;\n\tprotected disableSpring = false;\n\tprotected layoutState: PlayerLayoutState = {\n\t\tinterludeDotsSize: [0, 0],\n\t\ttargetAlignIndex: 0,\n\t\tlastInterludeState: false,\n\t\talignAnchor: LayoutAlignAnchor.Center,\n\t\talignPosition: 0.35,\n\t\toverscanPx: 300,\n\t};\n\tprotected interludeDots: InterludeDots = new InterludeDots();\n\tprotected bottomLine: BottomLineEl = new BottomLineEl(this);\n\tprotected enableBlur = true;\n\tprotected enableScale = true;\n\tprotected maskObsceneWords: MaskObsceneWordsMode =\n\t\tMaskObsceneWordsMode.Disabled;\n\tprotected maskObsceneWordChar = \"*\";\n\tprotected hidePassedLines = false;\n\tprotected scrollState: PlayerScrollState = {\n\t\tscrollBoundary: { minOffset: 0, maxOffset: 0 },\n\t\tscrollOffset: 0,\n\t\tallowScroll: true,\n\t\tisScrolled: false,\n\t\tisUserScrolling: false,\n\t};\n\tpublic currentLyricGroups: LyricLineGroupBase[] = [];\n\tlyricGroupSize: WeakMap<LyricLineGroupBase, [number, number]> = new WeakMap();\n\treadonly size: [number, number] = [0, 0];\n\tprotected isPageVisible = true;\n\tprotected optimizeOptions: OptimizeLyricOptions = {};\n\n\t/** 是否强制让背景人声行始终后置(即始终在主歌词下方显示,不前置背景人声) */\n\tprotected alwaysPostpositionBackground = false;\n\n\tprotected posXSpringParams: Partial<SpringParams> = {\n\t\tmass: 1,\n\t\tdamping: 10,\n\t\tstiffness: 100,\n\t};\n\tprotected posYSpringParams: Partial<SpringParams> = {\n\t\tmass: 0.9,\n\t\tdamping: 15,\n\t\tstiffness: 90,\n\t};\n\tprotected scaleSpringParams: Partial<SpringParams> = {\n\t\tmass: 2,\n\t\tdamping: 25,\n\t\tstiffness: 100,\n\t};\n\tprotected scaleForBGSpringParams: Partial<SpringParams> = {\n\t\tmass: 1,\n\t\tdamping: 20,\n\t\tstiffness: 50,\n\t};\n\tprivate onPageShow = () => {\n\t\tthis.isPageVisible = true;\n\t\tthis.setCurrentTime(this.timelineState.currentTime, true);\n\t};\n\tprivate onPageHide = () => {\n\t\tthis.isPageVisible = false;\n\t};\n\tprivate scrolledHandler: ReturnType<typeof setTimeout> | undefined;\n\t/** @internal */\n\tresizeObserver: ResizeObserver = new ResizeObserver(((entries) => {\n\t\tlet shouldRelayout = false;\n\t\tlet shouldRebuildPlayerStyle = false;\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.target === this.element) {\n\t\t\t\tconst rect = entry.contentRect;\n\t\t\t\tthis.size[0] = rect.width;\n\t\t\t\tthis.size[1] = rect.height;\n\t\t\t\tshouldRebuildPlayerStyle = true;\n\t\t\t} else if (entry.target === this.interludeDots.getElement()) {\n\t\t\t\tthis.layoutState.interludeDotsSize[0] = entry.target.clientWidth;\n\t\t\t\tthis.layoutState.interludeDotsSize[1] = entry.target.clientHeight;\n\t\t\t\tshouldRelayout = true;\n\t\t\t} else if (entry.target === this.bottomLine.getElement()) {\n\t\t\t\tconst newSize: [number, number] = [\n\t\t\t\t\tentry.target.clientWidth,\n\t\t\t\t\tentry.target.clientHeight,\n\t\t\t\t];\n\t\t\t\tconst oldSize: [number, number] = this.bottomLine.lineSize;\n\n\t\t\t\tif (newSize[0] !== oldSize[0] || newSize[1] !== oldSize[1]) {\n\t\t\t\t\tthis.bottomLine.lineSize = newSize;\n\t\t\t\t\tshouldRelayout = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst groupObj = this.lyricGroupElementMap.get(entry.target);\n\t\t\t\tif (groupObj) {\n\t\t\t\t\tconst newSize: [number, number] = [\n\t\t\t\t\t\tentry.target.clientWidth,\n\t\t\t\t\t\tentry.target.clientHeight,\n\t\t\t\t\t];\n\n\t\t\t\t\tconst oldSize: [number, number] = this.lyricGroupSize.get(\n\t\t\t\t\t\tgroupObj,\n\t\t\t\t\t) ?? [0, 0];\n\n\t\t\t\t\tif (newSize[0] !== oldSize[0] || newSize[1] !== oldSize[1]) {\n\t\t\t\t\t\tthis.lyricGroupSize.set(groupObj, newSize);\n\t\t\t\t\t\tgroupObj.onLineSizeChange(newSize);\n\t\t\t\t\t\tshouldRelayout = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (shouldRelayout) {\n\t\t\tthis.calcLayout(true);\n\t\t}\n\t\tif (shouldRebuildPlayerStyle) {\n\t\t\tthis.onResize();\n\t\t}\n\t}) as ResizeObserverCallback);\n\tprotected wordFadeWidth = 0.5;\n\n\tconstructor(element?: HTMLElement) {\n\t\tsuper();\n\t\tif (element) this.element = element;\n\t\tthis.element.classList.add(\"amll-lyric-player\");\n\n\t\tthis.resizeObserver.observe(this.element);\n\t\tthis.resizeObserver.observe(this.interludeDots.getElement());\n\n\t\tthis.element.appendChild(this.interludeDots.getElement());\n\t\tthis.element.appendChild(this.bottomLine.getElement());\n\t\tthis.interludeDots.setTransform(0, 200);\n\n\t\twindow.addEventListener(\"pageshow\", this.onPageShow);\n\t\twindow.addEventListener(\"pagehide\", this.onPageHide);\n\t\tattachPlayerScrollHandlers(this.element, this.scrollState, {\n\t\t\tonBeginScroll: () => this.beginScrollHandler(),\n\t\t\tonEndScroll: () => this.endScrollHandler(),\n\t\t\tonLayout: (sync, force) => this.calcLayout(sync, force),\n\t\t\tcontainsTarget: (target) => this.element.contains(target),\n\t\t\tclickTarget: (target) => target.click(),\n\t\t});\n\t}\n\n\tprivate beginScrollHandler() {\n\t\tconst allowed = this.scrollState.allowScroll;\n\t\tif (allowed) {\n\t\t\tthis.scrollState.isScrolled = true;\n\t\t\tclearTimeout(this.scrolledHandler);\n\t\t\tthis.scrolledHandler = setTimeout(() => {\n\t\t\t\tthis.scrollState.isScrolled = false;\n\t\t\t\tthis.scrollState.scrollOffset = 0;\n\t\t\t}, 5000);\n\t\t}\n\t\treturn allowed;\n\t}\n\tprivate endScrollHandler() {}\n\n\t/**\n\t * 设置文字动画的渐变宽度,单位以歌词行的主文字字体大小的倍数为单位,默认为 0.5,即一个全角字符的一半宽度\n\t *\n\t * 如果要模拟 Apple Music for Android 的效果,可以设置为 1\n\t *\n\t * 如果要模拟 Apple Music for iPad 的效果,可以设置为 0.5\n\t *\n\t * 如果想要近乎禁用渐变效果,可以设置成非常接近 0 的小数(例如 `0.0001` ),但是**不可以为 0**\n\t *\n\t * @param value 需要设置的渐变宽度,单位以歌词行的主文字字体大小的倍数为单位,默认为 0.5\n\t */\n\tsetWordFadeWidth(value = 0.5): void {\n\t\tthis.wordFadeWidth = Math.max(0.0001, value);\n\t}\n\n\t/**\n\t * 是否启用歌词行缩放效果,默认启用\n\t *\n\t * 如果启用,非选中的歌词行会轻微缩小以凸显当前播放歌词行效果\n\t *\n\t * 此效果对性能影响微乎其微,推荐启用\n\t * @param enable 是否启用歌词行缩放效果\n\t */\n\tsetEnableScale(enable = true): void {\n\t\tthis.enableScale = enable;\n\t\tthis.calcLayout();\n\t}\n\t/**\n\t * 获取当前是否启用了歌词行缩放效果\n\t * @returns 是否启用歌词行缩放效果\n\t */\n\tgetEnableScale(): boolean {\n\t\treturn this.enableScale;\n\t}\n\n\t/**\n\t * 获取当前文字动画的渐变宽度,单位以歌词行的主文字字体大小的倍数为单位\n\t * @returns 当前文字动画的渐变宽度,单位以歌词行的主文字字体大小的倍数为单位\n\t */\n\tgetWordFadeWidth(): number {\n\t\treturn this.wordFadeWidth;\n\t}\n\n\tsetIsSeeking(isSeeking: boolean): void {\n\t\tthis.timelineState.isSeeking = isSeeking;\n\t}\n\t/**\n\t * 设置是否隐藏已经播放过的歌词行,默认不隐藏\n\t * @param hide 是否隐藏已经播放过的歌词行,默认不隐藏\n\t */\n\tsetHidePassedLines(hide: boolean): void {\n\t\tthis.hidePassedLines = hide;\n\t\tthis.calcLayout();\n\t}\n\t/**\n\t * 设置是否启用歌词行的模糊效果\n\t * @param enable 是否启用\n\t */\n\tsetEnableBlur(enable: boolean): void {\n\t\tif (this.enableBlur === enable) return;\n\t\tthis.enableBlur = enable;\n\t\tthis.calcLayout();\n\t}\n\n\t/**\n\t * 设置歌词中不雅用语的掩码模式\n\t * @param mode 掩码模式\n\t * @see {@link MaskObsceneWordsMode}\n\t */\n\tsetMaskObsceneWords(mode: MaskObsceneWordsMode): void {\n\t\tif (this.maskObsceneWords === mode) return;\n\t\tthis.maskObsceneWords = mode;\n\t\tthis.rebuildLyricLines();\n\t\tthis.calcLayout();\n\t}\n\n\t/**\n\t * 设置不雅用语掩码使用的字符,默认为 `*`\n\t * @param char 单个字符,用于替换不雅用语中的字符\n\t */\n\tsetMaskObsceneWordChar(char: string): void {\n\t\tconst c = char.charAt(0) || \"*\";\n\t\tif (this.maskObsceneWordChar === c) return;\n\t\tthis.maskObsceneWordChar = c;\n\t\tif (this.maskObsceneWords !== MaskObsceneWordsMode.Disabled) {\n\t\t\tthis.rebuildLyricLines();\n\t\t\tthis.calcLayout();\n\t\t}\n\t}\n\n\trebuildLyricLines(): void {\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.rebuildAllLines();\n\t\t}\n\t}\n\t/**\n\t * 根据当前配置处理不雅用语单词\n\t * @param word 单词对象\n\t * @internal\n\t */\n\tprocessObsceneWord(word: LyricWord): string {\n\t\tconst text = word.word;\n\n\t\tif (\n\t\t\t!word.obscene ||\n\t\t\tthis.maskObsceneWords === MaskObsceneWordsMode.Disabled\n\t\t) {\n\t\t\treturn text;\n\t\t}\n\n\t\tconst maskChar = this.maskObsceneWordChar;\n\n\t\tif (this.maskObsceneWords === MaskObsceneWordsMode.FullMask) {\n\t\t\treturn text.replace(/\\S/g, maskChar);\n\t\t}\n\n\t\tif (this.maskObsceneWords === MaskObsceneWordsMode.PartialMask) {\n\t\t\tconst trimmed = text.trim();\n\n\t\t\tif (trimmed.length <= 2) {\n\t\t\t\treturn text.replace(/\\S/g, maskChar);\n\t\t\t}\n\n\t\t\tconst startPos = text.indexOf(trimmed);\n\t\t\tconst endPos = startPos + trimmed.length - 1;\n\n\t\t\treturn (\n\t\t\t\ttext.slice(0, startPos + 1) +\n\t\t\t\ttext.slice(startPos + 1, endPos).replace(/\\S/g, maskChar) +\n\t\t\t\ttext.slice(endPos)\n\t\t\t);\n\t\t}\n\n\t\treturn text;\n\t}\n\t/**\n\t * 设置目标歌词行的对齐方式,默认为 `center`\n\t *\n\t * - 设置成 `top` 的话将会向目标歌词行的顶部对齐\n\t * - 设置成 `bottom` 的话将会向目标歌词行的底部对齐\n\t * - 设置成 `center` 的话将会向目标歌词行的垂直中心对齐\n\t * @param alignAnchor 歌词行对齐方式,详情见函数说明\n\t */\n\tsetAlignAnchor(alignAnchor: LayoutAlignAnchor): void {\n\t\tthis.layoutState.alignAnchor = alignAnchor;\n\t}\n\t/**\n\t * 设置默认的歌词行对齐位置,相对于整个歌词播放组件的大小位置,默认为 `0.5`\n\t * @param alignPosition 一个 `[0.0-1.0]` 之间的任意数字,代表组件高度由上到下的比例位置\n\t */\n\tsetAlignPosition(alignPosition: number): void {\n\t\tthis.layoutState.alignPosition = alignPosition;\n\t}\n\n\t/**\n\t * 设置 overscan(视图上下额外缓冲渲染区)距离,单位:像素。\n\t * @param px 像素值,默认 300\n\t */\n\tsetOverscanPx(px: number): void {\n\t\tthis.layoutState.overscanPx = clampPositive(px | 0);\n\t}\n\t/** 获取当前 overscan 像素距离 */\n\tgetOverscanPx(): number {\n\t\treturn this.layoutState.overscanPx;\n\t}\n\t/**\n\t * 设置是否使用物理弹簧算法实现歌词动画效果,默认启用\n\t *\n\t * 如果启用,则会通过弹簧算法实时处理歌词位置,但是需要性能足够强劲的电脑方可流畅运行\n\t *\n\t * 如果不启用,则会回退到基于 `transition` 的过渡效果,对低性能的机器比较友好,但是效果会比较单一\n\t */\n\tsetEnableSpring(enable = true): void {\n\t\tthis.disableSpring = !enable;\n\t\tif (enable) {\n\t\t\tthis.element.classList.remove(styles.disableSpring);\n\t\t} else {\n\t\t\tthis.element.classList.add(styles.disableSpring);\n\t\t}\n\t\tthis.calcLayout(true);\n\t}\n\t/**\n\t * 获取当前是否启用了物理弹簧\n\t * @returns 是否启用物理弹簧\n\t */\n\tgetEnableSpring(): boolean {\n\t\treturn !this.disableSpring;\n\t}\n\n\t/**\n\t * 设置歌词的优化配置项,这些配置项默认全部开启\n\t *\n\t * 注意,如果在 `setLyricLines` 之后修改此配置,需要重新调用 `setLyricLines()` 才能对当前歌词生效\n\t * @param options 优化配置选项\n\t * @see {@link OptimizeLyricOptions}\n\t */\n\tsetOptimizeOptions(options: OptimizeLyricOptions): void {\n\t\tthis.optimizeOptions = { ...this.optimizeOptions, ...options };\n\t}\n\n\t/**\n\t * 设置当前播放歌词,要注意传入后这个数组内的信息不得修改,否则会发生错误\n\t * @param lines 歌词数组\n\t * @param initialTime 初始时间,默认为 0\n\t */\n\tsetLyricLines(lines: LyricLine[], initialTime = 0): void {\n\t\tif (import.meta.env.DEV) {\n\t\t\tconsole.log(\"设置歌词行\", lines, initialTime);\n\t\t}\n\n\t\tthis.timelineState.initialLayoutFinished = true;\n\t\tthis.timelineState.lastCurrentTime = initialTime;\n\t\tthis.timelineState.currentTime = initialTime;\n\n\t\tthis.currentLyricLines = structuredClone(lines);\n\t\tthis.processedLines = structuredClone(this.currentLyricLines);\n\t\toptimizeLyricLines(this.processedLines, this.optimizeOptions);\n\n\t\tthis.isNonDynamic = true;\n\t\tfor (const line of this.processedLines) {\n\t\t\tif (line.words.length > 1) {\n\t\t\t\tthis.isNonDynamic = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tthis.hasDuetLine = this.processedLines.some((line) => line.isDuet);\n\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.dispose();\n\t\t}\n\t\tthis.currentLyricGroups = [];\n\n\t\tthis.interludeDots.setInterlude(undefined);\n\t\tthis.timelineState.hotGroups.clear();\n\t\tthis.timelineState.bufferedGroups.clear();\n\n\t\tif (import.meta.env.DEV) {\n\t\t\tconsole.log(\"歌词处理完成\", this);\n\t\t}\n\t}\n\n\t/**\n\t * 获取当前是否在播放\n\t * @returns 当前是否在播放\n\t */\n\tpublic getIsPlaying(): boolean {\n\t\treturn this.timelineState.isPlaying;\n\t}\n\n\t/**\n\t * 设置当前播放进度,此时将会更新内部的歌词进度信息。\n\t *\n\t * 内部会根据调用间隔和播放进度自动决定如何滚动和显示歌词,所以这个的调用频率越快越准确越好。\n\t * 调用完成后,应每帧调用 {@link update} 方法来执行歌词动画效果。**此函数本身不会触发动画效果**。\n\t *\n\t * @param time 当前播放进度,单位为毫秒\n\t */\n\tsetCurrentTime(time: number, isSeek = false): void {\n\t\t// 歌词行为如下:\n\t\t// 如果当前仍有缓冲行的情况下加入新热行,则不会解除当前缓冲行,且也不会修改当前滚动位置\n\t\t// 如果当前所有缓冲行都将被删除且没有新热行加入,则删除所有缓冲行,且也不会修改当前滚动位置\n\t\t// 如果当前所有缓冲行都将被删除且有新热行加入,则删除所有缓冲行并加入新热行作为缓冲行,然后修改当前滚动位置\n\n\t\ttime = Math.round(time);\n\n\t\tconst { timelineState } = this;\n\t\ttimelineState.isSeeking = Boolean(isSeek);\n\t\ttimelineState.currentTime = time;\n\n\t\tif (!timelineState.initialLayoutFinished && !timelineState.isSeeking)\n\t\t\treturn;\n\n\t\tconst stateResult = computePlayerTimeState({\n\t\t\ttime,\n\t\t\tcurrentGroups: this.currentLyricGroups,\n\t\t\ttimelineState,\n\t\t});\n\n\t\tconst bottomEl = this.bottomLine.getElement();\n\t\tconst hasBottomContent = bottomEl.innerHTML.trim().length > 0;\n\t\tconst commitResult = commitPlayerTimeState({\n\t\t\ttimelineState: timelineState,\n\t\t\ttime,\n\t\t\tcurrentGroups: this.currentLyricGroups,\n\t\t\thasBottomContent,\n\t\t\tstateResult,\n\t\t});\n\n\t\tfor (const id of commitResult.groupsToDisable)\n\t\t\tthis.currentLyricGroups[id]?.disable();\n\n\t\tfor (const id of commitResult.groupsToEnable)\n\t\t\tthis.currentLyricGroups[id]?.enable();\n\n\t\tif (commitResult.shouldResetScroll) this.resetScroll();\n\t\tif (commitResult.shouldLayout) this.calcLayout();\n\t}\n\n\t/**\n\t * 重新布局定位歌词行的位置,调用完成后再逐帧调用 `update`\n\t * 函数即可让歌词通过动画移动到目标位置。\n\t *\n\t * 函数有一个 `force` 参数,用于指定是否强制修改布局,也就是不经过动画直接调整元素位置和大小。\n\t *\n\t * 此函数还有一个 `reflow` 参数,用于指定是否需要重新计算布局\n\t *\n\t * 因为计算布局必定会导致浏览器重排布局,所以会大幅度影响流畅度和性能,故请只在以下情况下将其​设置为 true:\n\t *\n\t * 1. 歌词页面大小发生改变时(这个组件会自行处理)\n\t * 2. 加载了新的歌词时(不论前后歌词是否完全一样)\n\t * 3. 用户自行跳转了歌曲播放位置(不论距离远近)\n\t *\n\t * @param sync 是否同步执行,通常用于初始化或 Resize 时立即布局\n\t * @param force 是否绕过弹簧效果强制更新位置\n\t */\n\tasync calcLayout(sync = false, force = false): Promise<void> {\n\t\tconst interlude = computeCurrentInterlude({\n\t\t\tcurrentTime: this.timelineState.currentTime,\n\t\t\tscrollToIndex: this.timelineState.scrollToIndex,\n\t\t\tcurrentGroups: this.currentLyricGroups,\n\t\t});\n\t\tconst isInterludeActive = !!interlude;\n\n\t\tif (\n\t\t\tthis.layoutState.targetAlignIndex !== this.timelineState.scrollToIndex ||\n\t\t\tthis.layoutState.lastInterludeState !== isInterludeActive\n\t\t) {\n\t\t\tthis.layoutState.lastInterludeState = isInterludeActive;\n\n\t\t\tconst springParams = computeLinePosYSpringParams({\n\t\t\t\tenabled: this.getEnableSpring(),\n\t\t\t\tcurrentGroups: this.currentLyricGroups,\n\t\t\t\tscrollToIndex: this.timelineState.scrollToIndex,\n\t\t\t\tisSeeking: this.timelineState.isSeeking,\n\t\t\t\tisInterludeActive,\n\t\t\t});\n\t\t\tif (springParams.shouldUpdate && springParams.params) {\n\t\t\t\tthis.setLinePosYSpringParams(springParams.params);\n\t\t\t}\n\t\t}\n\n\t\tlet curPos = -this.scrollState.scrollOffset;\n\t\tconst targetAlignIndex = this.timelineState.scrollToIndex;\n\t\tlet isNextDuet = false;\n\t\tif (interlude) {\n\t\t\tisNextDuet = interlude.isNextDuet;\n\t\t} else {\n\t\t\tthis.interludeDots.setInterlude(undefined);\n\t\t}\n\n\t\tconst fontSize = this.baseFontSize || 24;\n\t\tconst dotMargin = fontSize * 0.4;\n\t\tconst totalInterludeHeight =\n\t\t\tthis.layoutState.interludeDotsSize[1] + dotMargin * 2;\n\n\t\tif (interlude) {\n\t\t\tif (interlude.anchorLineIndex !== -1) {\n\t\t\t\tcurPos -= totalInterludeHeight;\n\t\t\t}\n\t\t}\n\t\t// 避免一开始就让所有歌词行挤在一起\n\t\tconst LINE_HEIGHT_FALLBACK = this.size[1] / 5;\n\t\tconst scrollOffset = this.currentLyricGroups\n\t\t\t.slice(0, targetAlignIndex)\n\t\t\t.reduce(\n\t\t\t\t(acc, group) =>\n\t\t\t\t\tacc + (this.lyricGroupSize.get(group)?.[1] ?? LINE_HEIGHT_FALLBACK),\n\t\t\t\t0,\n\t\t\t);\n\n\t\tthis.scrollState.scrollBoundary.minOffset = -scrollOffset;\n\t\tcurPos -= scrollOffset;\n\t\tcurPos += this.size[1] * this.layoutState.alignPosition;\n\n\t\tconst curGroup = this.currentLyricGroups[targetAlignIndex];\n\t\tthis.layoutState.targetAlignIndex = targetAlignIndex;\n\n\t\tconst isBottomFocused = targetAlignIndex === this.currentLyricGroups.length;\n\t\tthis.bottomLine.setFocused(isBottomFocused);\n\n\t\tconst targetLineHeight = curGroup\n\t\t\t? (this.lyricGroupSize.get(curGroup)?.[1] ?? LINE_HEIGHT_FALLBACK)\n\t\t\t: isBottomFocused\n\t\t\t\t? this.bottomLine.lineSize[1]\n\t\t\t\t: 0;\n\n\t\tif (targetLineHeight > 0) {\n\t\t\tswitch (this.layoutState.alignAnchor) {\n\t\t\t\tcase LayoutAlignAnchor.Bottom:\n\t\t\t\t\tcurPos -= targetLineHeight;\n\t\t\t\t\tbreak;\n\t\t\t\tcase LayoutAlignAnchor.Center:\n\t\t\t\t\tcurPos -= targetLineHeight / 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase LayoutAlignAnchor.Top:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tconst latestIndex = Math.max(...this.timelineState.bufferedGroups);\n\t\tlet delay = 0;\n\t\tlet baseDelay = sync ? 0 : 0.05;\n\t\tlet setDots = false;\n\n\t\tthis.currentLyricGroups.forEach((group, i) => {\n\t\t\tconst hasBuffered = this.timelineState.bufferedGroups.has(i);\n\n\t\t\tconst shouldShowDots = interlude && i === interlude.anchorLineIndex + 1;\n\n\t\t\tif (!setDots && shouldShowDots) {\n\t\t\t\tsetDots = true;\n\n\t\t\t\tcurPos += dotMargin;\n\n\t\t\t\tlet targetX = 0;\n\t\t\t\tif (interlude && isNextDuet) {\n\t\t\t\t\ttargetX = this.size[0] - this.layoutState.interludeDotsSize[0];\n\t\t\t\t}\n\n\t\t\t\tthis.interludeDots.setTransform(targetX, curPos);\n\n\t\t\t\tif (interlude) {\n\t\t\t\t\tthis.interludeDots.setInterlude([\n\t\t\t\t\t\tinterlude.startTime,\n\t\t\t\t\t\tinterlude.endTime,\n\t\t\t\t\t]);\n\t\t\t\t}\n\t\t\t\tcurPos += this.layoutState.interludeDotsSize[1];\n\t\t\t\tcurPos += dotMargin;\n\t\t\t}\n\n\t\t\tconst presentation = computeGroupPresentation({\n\t\t\t\tgroupIndex: i,\n\t\t\t\tscrollToIndex: this.timelineState.scrollToIndex,\n\t\t\t\tlatestIndex,\n\t\t\t\thasBuffered,\n\t\t\t\thidePassedLines: this.hidePassedLines,\n\t\t\t\tisPlaying: this.timelineState.isPlaying,\n\t\t\t\tisNonDynamic: this.isNonDynamic,\n\t\t\t\tenableBlur: this.enableBlur,\n\t\t\t\tisUserScrolling: this.scrollState.isUserScrolling,\n\t\t\t\tisCompact: window.innerWidth <= 1024,\n\t\t\t\tinterlude,\n\t\t\t});\n\n\t\t\tgroup.setTransform(\n\t\t\t\tcurPos,\n\t\t\t\tforce,\n\t\t\t\tdelay,\n\t\t\t\tpresentation.isActive,\n\t\t\t\tpresentation.targetOpacity,\n\t\t\t\tpresentation.blurLevel,\n\t\t\t);\n\n\t\t\tcurPos += this.lyricGroupSize.get(group)?.[1] ?? LINE_HEIGHT_FALLBACK;\n\n\t\t\tif (curPos >= 0 && !this.timelineState.isSeeking) {\n\t\t\t\tdelay += baseDelay;\n\t\t\t\tif (i >= this.timelineState.scrollToIndex) baseDelay /= 1.05;\n\t\t\t}\n\t\t});\n\t\tthis.scrollState.scrollBoundary.maxOffset =\n\t\t\tcurPos + this.scrollState.scrollOffset - this.size[1] / 2;\n\n\t\tconst bottomIndex = this.currentLyricGroups.length;\n\t\tconst finalBottomBlur = computeLineBlur({\n\t\t\tenableBlur: this.enableBlur,\n\t\t\tisUserScrolling: this.scrollState.isUserScrolling,\n\t\t\tisActive: isBottomFocused,\n\t\t\titemIndex: bottomIndex,\n\t\t\tscrollToIndex: this.timelineState.scrollToIndex,\n\t\t\tlatestIndex,\n\t\t\tisCompact: window.innerWidth <= 1024,\n\t\t});\n\n\t\tthis.bottomLine.setTransform(0, curPos, finalBottomBlur, force, delay);\n\t}\n\n\t/**\n\t * 设置所有歌词行在横坐标上的弹簧属性,包括重量、弹力和阻力。\n\t *\n\t * @param params 需要设置的弹簧属性,提供的属性将会覆盖原来的属性,未提供的属性将会保持原样\n\t * @deprecated 考虑到横向弹簧效果并不常见,所以这个函数将会在未来的版本中移除\n\t */\n\tsetLinePosXSpringParams(_params: Partial<SpringParams> = {}): void {}\n\t/**\n\t * 设置所有歌词行在​纵坐标上的弹簧属性,包括重量、弹力和阻力。\n\t *\n\t * @param params 需要设置的弹簧属性,提供的属性将会覆盖原来的属性,未提供的属性将会保持原样\n\t */\n\tsetLinePosYSpringParams(params: Partial<SpringParams> = {}): void {\n\t\tthis.posYSpringParams = {\n\t\t\t...this.posYSpringParams,\n\t\t\t...params,\n\t\t};\n\t\tthis.bottomLine.lineTransforms.posY.updateParams(this.posYSpringParams);\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.posY.updateParams(this.posYSpringParams);\n\t\t\tgroup.bgSlideY.updateParams(this.posYSpringParams);\n\t\t}\n\t}\n\t/**\n\t * 设置所有歌词行在​缩放大小上的弹簧属性,包括重量、弹力和阻力。\n\t *\n\t * @param params 需要设置的弹簧属性,提供的属性将会覆盖原来的属性,未提供的属性将会保持原样\n\t */\n\tsetLineScaleSpringParams(params: Partial<SpringParams> = {}): void {\n\t\tthis.scaleSpringParams = {\n\t\t\t...this.scaleSpringParams,\n\t\t\t...params,\n\t\t};\n\t\tthis.scaleForBGSpringParams = {\n\t\t\t...this.scaleForBGSpringParams,\n\t\t\t...params,\n\t\t};\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.mainLine.lineTransforms.scale.updateParams(this.scaleSpringParams);\n\n\t\t\tgroup.bgLine?.lineTransforms.scale.updateParams(\n\t\t\t\tthis.scaleForBGSpringParams,\n\t\t\t);\n\t\t}\n\t}\n\t/**\n\t * 暂停部分效果演出,目前会暂停播放间奏点的动画,且将背景歌词显示出来\n\t */\n\tpause(): void {\n\t\tthis.interludeDots.pause();\n\t\tif (this.timelineState.isPlaying) {\n\t\t\tthis.timelineState.isPlaying = false;\n\t\t\tthis.calcLayout();\n\t\t}\n\t}\n\t/**\n\t * 恢复部分效果演出,目前会恢复播放间奏点的动画\n\t */\n\tresume(): void {\n\t\tthis.interludeDots.resume();\n\t\tif (!this.timelineState.isPlaying) {\n\t\t\tthis.timelineState.isPlaying = true;\n\t\t\tthis.calcLayout();\n\t\t}\n\t}\n\t/**\n\t * 更新动画,这个函数应该被逐帧调用或者在以下情况下调用一次:\n\t *\n\t * 1. 刚刚调用完设置歌词函数的时候\n\t * @param delta 距离上一次被调用到现在的时长,单位为毫秒(可为浮点数)\n\t */\n\n\tupdate(delta = 0): void {\n\t\tthis.bottomLine.update(delta / 1000);\n\t\tthis.interludeDots.update(delta);\n\t}\n\n\tprotected onResize(): void {}\n\n\t/**\n\t * 获取一个特殊的底栏元素,默认是空白的,可以往内部添加任意元素\n\t *\n\t * 这个元素始终在歌词的底部,可以用于显示歌曲创作者等信息\n\t *\n\t * 但是请勿删除该元素,只能在内部存放元素\n\t *\n\t * @returns 一个元素,可以往内部添加任意元素\n\t */\n\tgetBottomLineElement(): HTMLElement {\n\t\treturn this.bottomLine.getElement();\n\t}\n\t/**\n\t * 重置用户滚动状态\n\t *\n\t * 请在用户完成滚动点击跳转歌词时调用本事件再调用 `calcLayout` 以正确滚动到目标位置\n\t */\n\tresetScroll(): void {\n\t\tresetPlayerScrollState(this.scrollState);\n\t\tclearTimeout(this.scrolledHandler);\n\t}\n\t/**\n\t * 获取当前歌词数组\n\t *\n\t * 一般和最后调用 `setLyricLines` 给予的参数一样\n\t * @returns 当前歌词数组\n\t */\n\tgetLyricLines(): LyricLine[] {\n\t\treturn this.currentLyricLines;\n\t}\n\t/**\n\t * 获取当前歌词的播放位置\n\t *\n\t * 一般和最后调用 `setCurrentTime` 给予的参数一样\n\t * @returns 当前播放位置\n\t */\n\tgetCurrentTime(): number {\n\t\treturn this.timelineState.currentTime;\n\t}\n\n\t/**\n\t * 设置是否让背景人声行始终后置显示\n\t *\n\t * 默认情况下,如果背景歌词开始时间早于主歌词,会在主歌词上方展示;\n\t * 如果设置为 `true`,则无论时间顺序如何,背景歌词都会始终在主歌词下方展示\n\t * @param enable 是否启用始终后置\n\t */\n\tsetAlwaysPostpositionBackground(enable: boolean): void {\n\t\tif (this.alwaysPostpositionBackground === enable) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.alwaysPostpositionBackground = enable;\n\n\t\tthis.rebuildLyricLines();\n\t\tthis.calcLayout();\n\t}\n\n\t/** 获取当前是否设置了让背景人声行始终后置显示 */\n\tgetAlwaysPostpositionBackground(): boolean {\n\t\treturn this.alwaysPostpositionBackground;\n\t}\n\n\tgetElement(): HTMLElement {\n\t\treturn this.element;\n\t}\n\tdispose(): void {\n\t\tthis.element.remove();\n\t\twindow.removeEventListener(\"pageshow\", this.onPageShow);\n\t\twindow.removeEventListener(\"pagehide\", this.onPageHide);\n\t}\n}\n","import type { Disposable } from \"#interfaces\";\nimport { Spring } from \"#utils/spring.ts\";\nimport { LyricLineRenderMode } from \"./consts.ts\";\nimport type { LyricLineBase } from \"./line.ts\";\n\nexport interface LyricPlayerFlags {\n\tgetEnableSpring(): boolean;\n\tgetEnableScale(): boolean;\n\tgetIsPlaying(): boolean;\n\tgetAlwaysPostpositionBackground(): boolean;\n}\n\nexport abstract class LyricLineGroupBase<\n\tT extends LyricLineBase = LyricLineBase,\n> implements Disposable\n{\n\tprotected abstract readonly lyricPlayer: LyricPlayerFlags;\n\n\tpublic posY: Spring = new Spring(0);\n\tpublic bgSlideY: Spring = new Spring(-80);\n\tpublic top = 0;\n\tpublic delay = 0;\n\n\tpublic isActive = false;\n\tpublic opacity = 1;\n\tpublic blur = 0;\n\n\tpublic isBgFirst = false;\n\n\tconstructor(\n\t\tpublic mainLine: T,\n\t\tpublic bgLine?: T | undefined,\n\t) {}\n\n\tget startTime(): number {\n\t\t// 优化歌词时 `syncMainAndBackgroundLines` 已经把时间同步好了,直接读取主歌词的即可\n\t\t// 要是用户关掉了这个优化,我们认为在这种情况下主歌词和背景人声显示不同步是符合用户预期的\n\t\treturn this.mainLine.getLine().startTime;\n\t}\n\n\tget endTime(): number {\n\t\treturn this.mainLine.getLine().endTime;\n\t}\n\n\tonLineSizeChange(size: [number, number]): void {\n\t\tthis.mainLine.onLineSizeChange(size);\n\t\tthis.bgLine?.onLineSizeChange(size);\n\t}\n\n\tsetTransform(\n\t\ttop: number,\n\t\tforce: boolean,\n\t\tdelay: number,\n\t\tisActive: boolean,\n\t\topacity: number,\n\t\tblur: number,\n\t): void {\n\t\tthis.top = top;\n\t\tthis.delay = delay;\n\t\tthis.isActive = isActive;\n\t\tthis.opacity = opacity;\n\t\tthis.blur = blur;\n\n\t\tthis.setLineTransformations(force, delay);\n\n\t\tconst enableSpring = this.lyricPlayer.getEnableSpring();\n\t\tconst alwaysPostposition =\n\t\t\tthis.lyricPlayer.getAlwaysPostpositionBackground();\n\t\tconst shouldBgFirst = alwaysPostposition ? false : this.isBgFirst;\n\t\tconst hiddenSlideY = shouldBgFirst ? 80 : -80;\n\n\t\tconst isPlaying = this.lyricPlayer.getIsPlaying();\n\n\t\tconst targetBgSlideY = isActive || !isPlaying ? 0 : hiddenSlideY;\n\n\t\tif (force || !enableSpring) {\n\t\t\tthis.posY.setPosition(top);\n\t\t\tthis.bgSlideY.setPosition(targetBgSlideY);\n\t\t\tthis.renderStyles();\n\t\t} else {\n\t\t\tthis.posY.setTargetPosition(top, delay);\n\t\t\tthis.bgSlideY.setTargetPosition(targetBgSlideY, delay);\n\t\t}\n\t}\n\n\tprivate setLineTransformations(force: boolean, delay: number) {\n\t\tconst enableScale = this.lyricPlayer.getEnableScale();\n\t\tconst isPlaying = this.lyricPlayer.getIsPlaying();\n\n\t\tconst renderMode = this.isActive\n\t\t\t? LyricLineRenderMode.GRADIENT\n\t\t\t: LyricLineRenderMode.SOLID;\n\n\t\tconst SCALE_ASPECT = enableScale ? 97 : 100;\n\t\tlet mainScale = 100;\n\t\tif (!this.isActive && isPlaying) {\n\t\t\tmainScale = SCALE_ASPECT;\n\t\t}\n\t\tthis.mainLine.setTransform(mainScale, 1, 0, force, delay, renderMode);\n\n\t\tlet bgScale = 100;\n\t\tif (!this.isActive && isPlaying) {\n\t\t\tbgScale = 75;\n\t\t}\n\t\tthis.bgLine?.setTransform(bgScale, 1, 0, force, delay, renderMode);\n\t}\n\n\tprotected abstract renderStyles(): void;\n\n\tabstract get isInSight(): boolean;\n\n\tupdate(delta: number): void {\n\t\tif (this.lyricPlayer.getEnableSpring()) {\n\t\t\tthis.posY.update(delta);\n\t\t\tthis.bgSlideY.update(delta);\n\t\t\tthis.renderStyles();\n\t\t}\n\n\t\tthis.mainLine.update(delta);\n\t\tthis.bgLine?.update(delta);\n\t}\n\n\trebuildAllLines(): void {\n\t\tthis.mainLine.rebuildElement();\n\t\tthis.bgLine?.rebuildElement();\n\t}\n\n\tenable(time?: number, shouldPlay?: boolean): void {\n\t\tthis.mainLine.enable(time, shouldPlay);\n\t\tthis.bgLine?.enable(time, shouldPlay);\n\t}\n\n\tdisable(): void {\n\t\tthis.mainLine.disable();\n\t\tthis.bgLine?.disable();\n\t}\n\n\tdispose(): void {\n\t\tthis.mainLine.dispose();\n\t\tthis.bgLine?.dispose();\n\t}\n}\n","import { LyricLineGroupBase } from \"#lyric/base/group.ts\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { clamp01 } from \"#utils/clamp.ts\";\nimport type { DomLyricPlayer } from \"./index.ts\";\nimport type { LyricLineEl } from \"./lyric-line.ts\";\n\nexport class LyricLineGroup extends LyricLineGroupBase<LyricLineEl> {\n\tpublic element: HTMLElement;\n\tpublic bgWrapper?: HTMLElement;\n\tprivate lastIsActive?: boolean;\n\n\tconstructor(\n\t\tpublic lyricPlayer: DomLyricPlayer,\n\t\tmainLine: LyricLineEl,\n\t) {\n\t\tsuper(mainLine);\n\t\tthis.element = document.createElement(\"div\");\n\t\tthis.element.className = styles.lyricLineWrapper;\n\t\tthis.element.appendChild(mainLine.getElement());\n\t\tthis.posY.setPosition(window.innerHeight * 2);\n\n\t\tlyricPlayer.resizeObserver.observe(this.element);\n\t}\n\n\tget isInSight(): boolean {\n\t\tconst t = this.posY.getCurrentPosition();\n\n\t\tlet h = this.lyricPlayer.lyricGroupSize?.get(this)?.[1];\n\t\tif (h === undefined || h === 0) {\n\t\t\th = this.element.clientHeight || 0;\n\t\t}\n\n\t\tconst pb = this.lyricPlayer.size[1];\n\t\tconst ov = this.lyricPlayer.getOverscanPx();\n\n\t\treturn !(t > pb + h + ov || t < -h - ov);\n\t}\n\n\tshow(): void {\n\t\tif (!this.element.parentElement) {\n\t\t\tconst playerEl = this.lyricPlayer.getElement();\n\t\t\tconst groups = this.lyricPlayer.currentLyricGroups;\n\t\t\tconst myIndex = groups.indexOf(this);\n\n\t\t\tlet referenceNode: HTMLElement | null = null;\n\t\t\tif (myIndex !== -1) {\n\t\t\t\tfor (let i = myIndex + 1; i < groups.length; i++) {\n\t\t\t\t\tif (groups[i].element.parentElement === playerEl) {\n\t\t\t\t\t\treferenceNode = groups[i].element;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tplayerEl.insertBefore(this.element, referenceNode);\n\n\t\t\tthis.lyricPlayer.resizeObserver.observe(this.element);\n\t\t}\n\n\t\tthis.mainLine.show();\n\t\tthis.bgLine?.show();\n\t}\n\n\thide(): void {\n\t\tif (this.element.parentElement) {\n\t\t\tthis.lyricPlayer.resizeObserver.unobserve(this.element);\n\t\t\tthis.element.remove();\n\n\t\t\tthis.mainLine.teardownContent();\n\t\t\tthis.bgLine?.teardownContent();\n\t\t}\n\t}\n\n\toverride update(delta: number): void {\n\t\tif (this.isInSight) {\n\t\t\tthis.show();\n\t\t} else {\n\t\t\tthis.hide();\n\t\t}\n\n\t\tsuper.update(delta);\n\t}\n\n\taddBgLine(bgLine: LyricLineEl): void {\n\t\tif (this.bgLine) {\n\t\t\tthis.bgLine.dispose();\n\t\t}\n\t\tif (this.bgWrapper) {\n\t\t\tthis.bgWrapper.remove();\n\t\t}\n\n\t\tthis.bgLine = bgLine;\n\n\t\t// 需要对比第一个词的开始时间而不是行起始时间,因为行的起始时间已经被\n\t\t// `syncMainAndBackgroundLines` 同步过了\n\t\tconst bgStartTime =\n\t\t\tbgLine.getLine().words[0]?.startTime ?? bgLine.getLine().startTime;\n\t\tconst mainStartTime =\n\t\t\tthis.mainLine.getLine().words[0]?.startTime ??\n\t\t\tthis.mainLine.getLine().startTime;\n\n\t\tthis.isBgFirst = bgStartTime < mainStartTime;\n\n\t\tif (this.mainLine.getLine().isDuet) {\n\t\t\tbgLine.getElement().classList.add(styles.lyricDuetLine);\n\t\t}\n\n\t\tthis.bgWrapper = document.createElement(\"div\");\n\t\tthis.bgWrapper.className = styles.bgWrapper;\n\n\t\tthis.bgWrapper.appendChild(bgLine.getElement());\n\n\t\tconst alwaysPostposition =\n\t\t\tthis.lyricPlayer.getAlwaysPostpositionBackground();\n\t\tconst shouldBgFirst = !alwaysPostposition && this.isBgFirst;\n\n\t\tif (shouldBgFirst) {\n\t\t\tthis.bgWrapper.classList.add(styles.bgWrapperTop);\n\t\t\tthis.element.insertBefore(this.bgWrapper, this.mainLine.getElement());\n\t\t\tthis.bgSlideY.setPosition(80);\n\t\t} else {\n\t\t\tthis.element.appendChild(this.bgWrapper);\n\t\t}\n\t}\n\n\tprotected renderStyles(): void {\n\t\tconst y = this.posY.getCurrentPosition().toFixed(1);\n\n\t\tthis.element.style.transform = `translateY(${y}px)`;\n\t\tthis.element.style.opacity = this.opacity.toString();\n\t\tthis.element.style.filter = `blur(${Math.min(5, this.blur)}px)`;\n\n\t\tif (!this.lyricPlayer.getEnableSpring()) {\n\t\t\tthis.element.style.transitionDelay = `${this.delay}ms`;\n\t\t}\n\n\t\tif (this.bgWrapper) {\n\t\t\tif (this.lastIsActive !== this.isActive) {\n\t\t\t\tthis.lastIsActive = this.isActive;\n\t\t\t\tthis.bgWrapper.classList.toggle(styles.bgWrapperActive, this.isActive);\n\t\t\t}\n\n\t\t\tconst slideY = this.bgSlideY.getCurrentPosition();\n\t\t\tconst slideYStr = slideY.toFixed(1);\n\t\t\tconst activeProgress = clamp01(1 - Math.abs(slideY) / 80);\n\n\t\t\tconst scaleStr = (0.8 + activeProgress * 0.2).toFixed(3);\n\t\t\tthis.bgWrapper.style.transform = `translateY(${slideYStr}%) scale(${scaleStr})`;\n\n\t\t\tconst alwaysPostposition =\n\t\t\t\tthis.lyricPlayer.getAlwaysPostpositionBackground();\n\t\t\tconst shouldBgFirst = !alwaysPostposition && this.isBgFirst;\n\n\t\t\tif (shouldBgFirst) {\n\t\t\t\tconst bgHeight = this.bgWrapper.clientHeight || 0;\n\t\t\t\tconst currentMarginTop = -bgHeight * (1 - activeProgress);\n\t\t\t\tthis.bgWrapper.style.marginTop = `${currentMarginTop.toFixed(1)}px`;\n\t\t\t} else {\n\t\t\t\tthis.bgWrapper.style.marginTop = \"\";\n\t\t\t}\n\n\t\t\tconst targetHiddenYStr = shouldBgFirst ? \"80.0\" : \"-80.0\";\n\t\t\tconst isHidden = slideYStr === targetHiddenYStr && !this.isActive;\n\t\t\tthis.bgWrapper.classList.toggle(styles.bgWrapperHidden, isHidden);\n\t\t}\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tthis.lyricPlayer.resizeObserver.unobserve(this.element);\n\t\tthis.element.remove();\n\t}\n}\n","export const isCJK = (char: string): boolean => {\n\treturn /^[\\p{Unified_Ideograph}\\u0800-\\u9FFC]+$/u.test(char);\n};\n","import type { Disposable, LyricLine, LyricWord } from \"#interfaces\";\nimport { isCJK } from \"#utils/is-cjk.ts\";\nimport { Spring } from \"#utils/spring.ts\";\nimport { LyricLineRenderMode } from \"./consts.ts\";\n\ninterface LineTransforms {\n\tscale: Spring;\n}\n\n/**\n * 所有标准歌词行的基类\n * @internal\n */\nexport abstract class LyricLineBase extends EventTarget implements Disposable {\n\tprotected top = 0;\n\tprotected scale = 1;\n\tprotected blur = 0;\n\tprotected opacity = 1;\n\tprotected delay = 0;\n\treadonly lineTransforms: LineTransforms = {\n\t\tscale: new Spring(100),\n\t};\n\n\t/**\n\t * 用于 CJK 词语边界检测的分词器\n\t */\n\tstatic readonly wordSegmenter: Intl.Segmenter | null =\n\t\ttypeof Intl !== \"undefined\" && Intl.Segmenter\n\t\t\t? new Intl.Segmenter(undefined, { granularity: \"word\" })\n\t\t\t: null;\n\n\t/**\n\t * Unicode 标准的全局 Grapheme Cluster 分词器\n\t * 用于正确处理 emoji、复合字符等\n\t */\n\tstatic readonly graphemeSegmenter: Intl.Segmenter | null =\n\t\ttypeof Intl !== \"undefined\" && Intl.Segmenter\n\t\t\t? new Intl.Segmenter(undefined, { granularity: \"grapheme\" })\n\t\t\t: null;\n\n\tabstract getLine(): LyricLine;\n\tabstract enable(time?: number, shouldPlay?: boolean): void;\n\tabstract disable(): void;\n\tabstract resume(): void;\n\tabstract pause(): void;\n\tabstract onLineSizeChange(size: [number, number]): void;\n\n\tsetTransform(\n\t\tscale: number = this.scale,\n\t\topacity: number = this.opacity,\n\t\tblur: number = this.blur,\n\t\t_force = false,\n\t\tdelay = 0,\n\t\t_mode: LyricLineRenderMode = LyricLineRenderMode.SOLID,\n\t): void {\n\t\tthis.scale = scale;\n\t\tthis.opacity = opacity;\n\t\tthis.blur = blur;\n\t\tthis.delay = delay;\n\t}\n\n\trebuildElement(): void {}\n\n\t/**\n\t * 判定歌词是否可以应用强调辉光效果\n\t *\n\t * 果子在对辉光效果的解释是一种强调(emphasized)效果\n\t *\n\t * 条件是一个单词时长大于等于 1s 且长度小于等于 7\n\t *\n\t * @param word 单词\n\t * @returns 是否可以应用强调辉光效果\n\t */\n\tstatic shouldEmphasize(word: LyricWord): boolean {\n\t\tif (isCJK(word.word)) return word.endTime - word.startTime >= 1000;\n\n\t\treturn (\n\t\t\tword.endTime - word.startTime >= 1000 &&\n\t\t\tword.word.trim().length <= 7 &&\n\t\t\tword.word.trim().length > 1\n\t\t);\n\t}\n\tabstract update(delta?: number): void;\n\tdispose(): void {}\n}\n","import { isCJK } from \"./is-cjk.ts\";\n\nexport interface ChildNodeInfo {\n\twidth: number;\n\ttext: string;\n\tisSpace: boolean;\n}\n\n/**\n * 单个词超过容器宽度时的大惩罚倍数\n */\nconst OVERFLOW_PENALTY_MULTIPLIER = 1000;\n/**\n * 截断 CJK 词组边界的惩罚比例\n *\n * 相对于容器宽度\n */\nconst CJK_BREAK_PENALTY_RATIO = 0.15;\n/**\n * 截断普通文本(非空格、非 CJK 词界)的惩罚比例\n */\nconst NORMAL_BREAK_PENALTY_RATIO = 0.5;\n/**\n * 在空格处断开的奖励比例\n */\nconst SPACE_BREAK_REWARD_RATIO = 0.4;\n/**\n * 在标点符号处断开的奖励比例\n *\n * 比空格更高以便优先一点在标点处换行\n */\nconst PUNCTUATION_BREAK_REWARD_RATIO = 0.6;\nconst PUNCTUATION_REGEX = /[,.;:!?,。;:!?、)】》」』’”)[\\]}>~…]$/;\n\n/**\n * 计算平均行长度的断点位置\n * @param children 子节点信息\n * @param containerWidth 容器可用内容宽度\n * @param fullText 完整的行文本\n * @param segmenter 预创建的 Intl.Segmenter 分词器\n * @returns 需要在其前面插入 `<br>` 的子节点索引数组,升序\n */\nexport function calcBalancedBreaks(\n\tchildren: ChildNodeInfo[],\n\tcontainerWidth: number,\n\tfullText: string,\n\tsegmenter: Intl.Segmenter,\n): number[] {\n\tconst n = children.length;\n\tif (n === 0 || containerWidth <= 0) {\n\t\treturn [];\n\t}\n\n\t// 计算哪里是 CJK 词组的边界\n\tconst cjkBoundaries = new Set<number>();\n\tlet offset = 0;\n\tfor (const { segment, isWordLike } of segmenter.segment(fullText)) {\n\t\tif (offset > 0 && isWordLike) {\n\t\t\tif ([...segment].some((ch) => isCJK(ch))) {\n\t\t\t\tcjkBoundaries.add(offset);\n\t\t\t}\n\t\t}\n\t\toffset += segment.length;\n\t}\n\n\t// 计算前缀宽和字符偏移量用于快速查询\n\tconst charOffsets = new Int32Array(n + 1);\n\tconst prefixWidth = new Float64Array(n + 1);\n\tfor (let i = 0; i < n; i++) {\n\t\tcharOffsets[i + 1] = charOffsets[i] + children[i].text.length;\n\t\tprefixWidth[i + 1] = prefixWidth[i] + children[i].width;\n\t}\n\n\tif (prefixWidth[n] <= containerWidth) {\n\t\treturn [];\n\t}\n\n\t/**\n\t * dp[i] 表示将 index i 到 n-1 的节点进行排版的最小代价\n\t */\n\tconst dp = new Float64Array(n + 1).fill(Number.POSITIVE_INFINITY);\n\tconst nextBreak = new Int32Array(n + 1).fill(-1);\n\tdp[n] = 0;\n\n\tconst PENALTY_CJK = (containerWidth * CJK_BREAK_PENALTY_RATIO) ** 2;\n\tconst PENALTY_NORMAL = (containerWidth * NORMAL_BREAK_PENALTY_RATIO) ** 2;\n\n\tfor (let i = n - 1; i >= 0; i--) {\n\t\tfor (let j = i + 1; j <= n; j++) {\n\t\t\tconst w = prefixWidth[j] - prefixWidth[i];\n\n\t\t\tlet lineCost = 0;\n\n\t\t\tif (w > containerWidth) {\n\t\t\t\tif (j === i + 1) {\n\t\t\t\t\t// 单个无法分割的词自身就比容器宽,被迫独立成行,给大惩罚\n\t\t\t\t\tlineCost = (w - containerWidth) ** 2 * OVERFLOW_PENALTY_MULTIPLIER;\n\t\t\t\t} else {\n\t\t\t\t\t// 行内包含多个超过物理宽度的词就跳过\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// 迫使所有行的长度方差最小化\n\t\t\t\tlineCost = (containerWidth - w) ** 2;\n\t\t\t}\n\n\t\t\tlet breakPenalty = 0;\n\t\t\tif (j < n) {\n\t\t\t\tconst prevChild = children[j - 1];\n\n\t\t\t\t// 优先级:标点 > 空格 > CJK 词界 > 普通文本\n\t\t\t\tif (PUNCTUATION_REGEX.test(prevChild.text)) {\n\t\t\t\t\tbreakPenalty = -(\n\t\t\t\t\t\t(containerWidth * PUNCTUATION_BREAK_REWARD_RATIO) **\n\t\t\t\t\t\t2\n\t\t\t\t\t);\n\t\t\t\t} else if (prevChild.isSpace) {\n\t\t\t\t\tbreakPenalty = -((containerWidth * SPACE_BREAK_REWARD_RATIO) ** 2);\n\t\t\t\t} else if (cjkBoundaries.has(charOffsets[j])) {\n\t\t\t\t\tbreakPenalty = PENALTY_CJK;\n\t\t\t\t} else {\n\t\t\t\t\tbreakPenalty = PENALTY_NORMAL;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst totalCost = lineCost + breakPenalty + dp[j];\n\n\t\t\tif (totalCost < dp[i]) {\n\t\t\t\tdp[i] = totalCost;\n\t\t\t\tnextBreak[i] = j;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst breaks: number[] = [];\n\tlet curr = 0;\n\twhile (curr < n) {\n\t\tcurr = nextBreak[curr];\n\t\tif (curr > 0 && curr < n) {\n\t\t\tbreaks.push(curr);\n\t\t}\n\t}\n\n\treturn breaks;\n}\n","import { clampPositive } from \"./clamp.ts\";\nimport { type ChildNodeInfo, calcBalancedBreaks } from \"./lyric-line-break.ts\";\n\nlet sharedCanvasCtx: CanvasRenderingContext2D | null = null;\nexport function getMeasurementContext(): CanvasRenderingContext2D | null {\n\tif (!sharedCanvasCtx) {\n\t\tconst canvas = document.createElement(\"canvas\");\n\t\tsharedCanvasCtx = canvas.getContext(\"2d\");\n\t}\n\treturn sharedCanvasCtx;\n}\n\ninterface LineBalanceAdapter {\n\tresetDOM(): void;\n\tbuildChildInfos(): { childInfos: ChildNodeInfo[]; fullText: string };\n\tapplyBreaks(breaks: number[], childInfos: ChildNodeInfo[]): void;\n\tneedsCalibration: boolean;\n}\n\n/**\n * 用于平衡歌词行在换行后的各行长度\n */\nexport class LineBalancer {\n\tprivate isBalancing = false;\n\tprivate lastBalancedContainerWidth = -1;\n\n\tconstructor(private mainElement: HTMLDivElement) {}\n\n\tpublic balanceLineBreaks(\n\t\tisNonDynamic: boolean,\n\t\thasSplittedWords: boolean,\n\t\twordSegmenter: Intl.Segmenter,\n\t): void {\n\t\tif (this.isBalancing || !this.mainElement) return;\n\n\t\tconst computedStyle = getComputedStyle(this.mainElement);\n\t\tconst paddingLeft = Number.parseFloat(computedStyle.paddingLeft) || 0;\n\t\tconst paddingRight = Number.parseFloat(computedStyle.paddingRight) || 0;\n\t\tconst containerWidth =\n\t\t\tthis.mainElement.clientWidth - paddingLeft - paddingRight;\n\n\t\tif (containerWidth <= 0) return;\n\n\t\tif (isNonDynamic) {\n\t\t\tthis.balanceNonDynamicLineBreaks(\n\t\t\t\tcontainerWidth,\n\t\t\t\tcomputedStyle,\n\t\t\t\twordSegmenter,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!hasSplittedWords) return;\n\t\tthis.balanceDynamicLineBreaks(containerWidth, wordSegmenter);\n\t}\n\n\tpublic reset(): void {\n\t\tthis.lastBalancedContainerWidth = -1;\n\t}\n\n\tprivate executeLineBalance(\n\t\tcontainerWidth: number,\n\t\tadapter: LineBalanceAdapter,\n\t\twordSegmenter: Intl.Segmenter,\n\t): void {\n\t\tconst existingBrs = this.mainElement.querySelectorAll(\"br\");\n\t\tif (\n\t\t\tcontainerWidth === this.lastBalancedContainerWidth &&\n\t\t\texistingBrs.length > 0\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tadapter.resetDOM();\n\n\t\t// 临时设置 white-space: nowrap 以便测量单个歌词行的宽度\n\t\tconst prevWhiteSpace = this.mainElement.style.whiteSpace;\n\t\tthis.mainElement.style.whiteSpace = \"nowrap\";\n\n\t\t// 临时移除父级的 transform 以便让 getBoundingClientRect 返回纯粹的布局尺寸\n\t\t// 基类在 enableScale 时设置的 0.97 缩放倍率会影响到计算的宽度\n\t\tconst parentElement = this.mainElement.parentElement;\n\t\tlet prevTransform = \"\";\n\t\tlet transformChanged = false;\n\n\t\tif (parentElement) {\n\t\t\tprevTransform = parentElement.style.transform;\n\t\t\tif (prevTransform && prevTransform !== \"none\") {\n\t\t\t\tparentElement.style.transform = \"none\";\n\t\t\t\ttransformChanged = true;\n\t\t\t}\n\t\t}\n\n\t\tlet lockAcquired = false;\n\n\t\ttry {\n\t\t\tconst { childInfos, fullText } = adapter.buildChildInfos();\n\n\t\t\tlet layoutWidth = childInfos.reduce((sum, c) => sum + c.width, 0);\n\n\t\t\t// 非动态歌词(用 Canvas 测量)才用 range 来缩放校准;动态歌词的强调 wrapper 有 1em 的 padding 和\n\t\t\t// margin,用 range 测会把首尾溢出的 1em 也加进来,极大地增大了行长度,视觉上就是非常激进地换行\n\t\t\tif (adapter.needsCalibration) {\n\t\t\t\tconst range = document.createRange();\n\t\t\t\trange.selectNodeContents(this.mainElement);\n\t\t\t\tconst visualWidth = range.getBoundingClientRect().width;\n\n\t\t\t\tif (layoutWidth > 0 && visualWidth > 0) {\n\t\t\t\t\tconst scale = visualWidth / layoutWidth;\n\t\t\t\t\tfor (const info of childInfos) {\n\t\t\t\t\t\tinfo.width *= scale;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlayoutWidth = visualWidth;\n\t\t\t}\n\n\t\t\tconst safeContainerWidth = Math.max(1, containerWidth);\n\n\t\t\tif (layoutWidth <= safeContainerWidth) {\n\t\t\t\tthis.lastBalancedContainerWidth = containerWidth;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst breaks = calcBalancedBreaks(\n\t\t\t\tchildInfos,\n\t\t\t\tsafeContainerWidth,\n\t\t\t\tfullText,\n\t\t\t\twordSegmenter,\n\t\t\t);\n\n\t\t\tif (breaks.length === 0) {\n\t\t\t\tthis.lastBalancedContainerWidth = containerWidth;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.isBalancing = true;\n\t\t\tlockAcquired = true;\n\n\t\t\tadapter.applyBreaks(breaks, childInfos);\n\t\t\tthis.lastBalancedContainerWidth = containerWidth;\n\t\t\tthis.isBalancing = false;\n\t\t} finally {\n\t\t\tthis.mainElement.style.whiteSpace = prevWhiteSpace;\n\t\t\tif (transformChanged && parentElement) {\n\t\t\t\tparentElement.style.transform = prevTransform;\n\t\t\t}\n\n\t\t\tif (lockAcquired) {\n\t\t\t\tthis.isBalancing = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate balanceDynamicLineBreaks(\n\t\tcontainerWidth: number,\n\t\twordSegmenter: Intl.Segmenter,\n\t): void {\n\t\tconst infoToNode: Node[] = [];\n\n\t\tconst dynamicAdapter: LineBalanceAdapter = {\n\t\t\tresetDOM: () => {\n\t\t\t\tthis.mainElement.querySelectorAll(\"br\").forEach((br) => {\n\t\t\t\t\tbr.remove();\n\t\t\t\t});\n\t\t\t},\n\t\t\tbuildChildInfos: () => {\n\t\t\t\tinfoToNode.length = 0;\n\t\t\t\tconst childNodes = Array.from(this.mainElement.childNodes);\n\t\t\t\tconst childInfos: ChildNodeInfo[] = [];\n\t\t\t\tconst range = document.createRange();\n\n\t\t\t\tfor (const node of childNodes) {\n\t\t\t\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\t\t\t\tconst text = node.textContent ?? \"\";\n\t\t\t\t\t\tif (text.length === 0) continue;\n\t\t\t\t\t\trange.selectNodeContents(node);\n\t\t\t\t\t\tchildInfos.push({\n\t\t\t\t\t\t\twidth: range.getBoundingClientRect().width,\n\t\t\t\t\t\t\ttext,\n\t\t\t\t\t\t\tisSpace: text.trim().length === 0,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tinfoToNode.push(node);\n\t\t\t\t\t} else if (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\tconst el = node as HTMLElement;\n\t\t\t\t\t\tconst rect = el.getBoundingClientRect();\n\t\t\t\t\t\tconst elStyle = getComputedStyle(el);\n\t\t\t\t\t\tconst marginLeft = Number.parseFloat(elStyle.marginLeft) || 0;\n\t\t\t\t\t\tconst marginRight = Number.parseFloat(elStyle.marginRight) || 0;\n\t\t\t\t\t\tchildInfos.push({\n\t\t\t\t\t\t\twidth: clampPositive(rect.width + marginLeft + marginRight),\n\t\t\t\t\t\t\ttext: el.textContent ?? \"\",\n\t\t\t\t\t\t\tisSpace: false,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tinfoToNode.push(node);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { childInfos, fullText: childInfos.map((c) => c.text).join(\"\") };\n\t\t\t},\n\t\t\tapplyBreaks: (breaks) => {\n\t\t\t\tfor (let i = breaks.length - 1; i >= 0; i--) {\n\t\t\t\t\tconst breakIndex = breaks[i];\n\t\t\t\t\tif (breakIndex >= 0 && breakIndex < infoToNode.length) {\n\t\t\t\t\t\tthis.mainElement.insertBefore(\n\t\t\t\t\t\t\tdocument.createElement(\"br\"),\n\t\t\t\t\t\t\tinfoToNode[breakIndex],\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tneedsCalibration: false,\n\t\t};\n\n\t\tthis.executeLineBalance(containerWidth, dynamicAdapter, wordSegmenter);\n\t}\n\n\tprivate balanceNonDynamicLineBreaks(\n\t\tcontainerWidth: number,\n\t\tcomputedStyle: CSSStyleDeclaration,\n\t\twordSegmenter: Intl.Segmenter,\n\t): void {\n\t\tconst fullText = this.mainElement.textContent ?? \"\";\n\t\tif (fullText.trim().length === 0) return;\n\n\t\tconst nonDynamicAdapter: LineBalanceAdapter = {\n\t\t\tresetDOM: () => {\n\t\t\t\tthis.mainElement.innerHTML = \"\";\n\t\t\t\tthis.mainElement.textContent = fullText;\n\t\t\t},\n\t\t\tbuildChildInfos: () => {\n\t\t\t\tconst ctx = getMeasurementContext();\n\n\t\t\t\tif (!ctx) {\n\t\t\t\t\tconsole.debug(\n\t\t\t\t\t\t\"Canvas 2D context is not supported, skipping line balancing\",\n\t\t\t\t\t);\n\t\t\t\t\treturn { childInfos: [], fullText };\n\t\t\t\t}\n\n\t\t\t\tctx.font = `${computedStyle.fontWeight} ${computedStyle.fontSize} ${computedStyle.fontFamily}`;\n\n\t\t\t\tif (\"letterSpacing\" in ctx) {\n\t\t\t\t\tctx.letterSpacing =\n\t\t\t\t\t\tcomputedStyle.letterSpacing !== \"normal\"\n\t\t\t\t\t\t\t? computedStyle.letterSpacing\n\t\t\t\t\t\t\t: \"0px\";\n\t\t\t\t}\n\t\t\t\tif (\"wordSpacing\" in ctx) {\n\t\t\t\t\tctx.wordSpacing =\n\t\t\t\t\t\tcomputedStyle.wordSpacing !== \"normal\"\n\t\t\t\t\t\t\t? computedStyle.wordSpacing\n\t\t\t\t\t\t\t: \"0px\";\n\t\t\t\t}\n\n\t\t\t\tconst childInfos: ChildNodeInfo[] = [];\n\t\t\t\tfor (const { segment } of wordSegmenter.segment(fullText)) {\n\t\t\t\t\tchildInfos.push({\n\t\t\t\t\t\twidth: ctx.measureText(segment).width,\n\t\t\t\t\t\ttext: segment,\n\t\t\t\t\t\tisSpace: segment.trim().length === 0,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn { childInfos, fullText };\n\t\t\t},\n\t\t\tapplyBreaks: (breaks, childInfos) => {\n\t\t\t\tthis.mainElement.innerHTML = \"\";\n\t\t\t\tconst breakSet = new Set(breaks);\n\t\t\t\tconst fragment = document.createDocumentFragment();\n\n\t\t\t\tfor (let i = 0; i < childInfos.length; i++) {\n\t\t\t\t\tif (breakSet.has(i)) {\n\t\t\t\t\t\tfragment.appendChild(document.createElement(\"br\"));\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild(document.createTextNode(childInfos[i].text));\n\t\t\t\t}\n\t\t\t\tthis.mainElement.appendChild(fragment);\n\t\t\t},\n\t\t\tneedsCalibration: true,\n\t\t};\n\n\t\tthis.executeLineBalance(containerWidth, nonDynamicAdapter, wordSegmenter);\n\t}\n}\n","import type { LyricWord } from \"../interfaces.ts\";\nimport { isCJK } from \"./is-cjk.ts\";\n\nconst SPLIT_WHITESPACE_RE = /(\\s+)/;\nconst WHITESPACE_RE = /\\s/g;\n\n/**\n * 将输入的单词重新分组,之间没有空格的单词将会组合成一个单词数组\n *\n * 例如输入:`[\"Life\", \" \", \"is\", \" a\", \" su\", \"gar so\", \"sweet\"]`\n *\n * 应该返回:`[\"Life\", \" \", \"is\", \" a\", [\" su\", \"gar\"], \"so\", \"sweet\"]`\n * @param words 输入的单词数组\n * @returns 重新分组后的单词数组\n */\nexport function chunkAndSplitLyricWords(\n\twords: LyricWord[],\n): (LyricWord | LyricWord[])[] {\n\tconst result: (LyricWord | LyricWord[])[] = [];\n\tlet currentGroup: LyricWord[] = [];\n\n\tconst flushGroup = () => {\n\t\tif (currentGroup.length > 0) {\n\t\t\tresult.push(\n\t\t\t\tcurrentGroup.length === 1 ? currentGroup[0] : [...currentGroup],\n\t\t\t);\n\t\t\tcurrentGroup = [];\n\t\t}\n\t};\n\n\tconst processAtom = (atom: LyricWord) => {\n\t\tconst isSpace = atom.word.trim().length === 0;\n\t\tconst hasRuby = (atom.ruby?.length ?? 0) > 0;\n\t\tconst isCJKChar = isCJK(atom.word);\n\n\t\tconst isMergeable = !isSpace && !hasRuby && !isCJKChar;\n\n\t\tif (isMergeable) {\n\t\t\tcurrentGroup.push(atom);\n\t\t} else {\n\t\t\tflushGroup();\n\t\t\tresult.push(atom);\n\t\t}\n\t};\n\n\tfor (const w of words) {\n\t\tconst content = w.word.trim();\n\t\tconst isSpace = content.length === 0;\n\t\tconst romanWord = w.romanWord ?? \"\";\n\t\tconst obscene = w.obscene ?? false;\n\t\tconst hasRuby = (w.ruby?.length ?? 0) > 0;\n\n\t\tif (isSpace || hasRuby) {\n\t\t\tprocessAtom({ ...w });\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst parts = w.word.split(SPLIT_WHITESPACE_RE).filter((p) => p.length > 0);\n\n\t\tconst totalLength = w.word.replace(WHITESPACE_RE, \"\").length || 1;\n\t\tconst timeSpan = w.endTime - w.startTime;\n\t\tconst timePerUnit = timeSpan / totalLength;\n\n\t\tlet currentOffset = 0;\n\n\t\tfor (const part of parts) {\n\t\t\tif (!part.trim()) {\n\t\t\t\tconst startTime = w.startTime + currentOffset * timePerUnit;\n\t\t\t\tprocessAtom({\n\t\t\t\t\tword: part,\n\t\t\t\t\tromanWord: \"\",\n\t\t\t\t\tstartTime: startTime,\n\t\t\t\t\tendTime: startTime,\n\t\t\t\t\tobscene: obscene,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isCJK(part) && part.length > 1 && romanWord.trim().length === 0) {\n\t\t\t\tconst chars = part.split(\"\");\n\t\t\t\tfor (const char of chars) {\n\t\t\t\t\tconst startTime = w.startTime + currentOffset * timePerUnit;\n\t\t\t\t\tprocessAtom({\n\t\t\t\t\t\tword: char,\n\t\t\t\t\t\tromanWord: \"\",\n\t\t\t\t\t\tstartTime: startTime,\n\t\t\t\t\t\tendTime: startTime + timePerUnit,\n\t\t\t\t\t\tobscene: obscene,\n\t\t\t\t\t});\n\t\t\t\t\tcurrentOffset += 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst partRealLen = part.length;\n\t\t\t\tconst startTime = w.startTime + currentOffset * timePerUnit;\n\t\t\t\tconst duration = partRealLen * timePerUnit;\n\n\t\t\t\tprocessAtom({\n\t\t\t\t\tword: part,\n\t\t\t\t\tromanWord: romanWord,\n\t\t\t\t\tstartTime: startTime,\n\t\t\t\t\tendTime: startTime + duration,\n\t\t\t\t\tobscene: obscene,\n\t\t\t\t});\n\t\t\t\tcurrentOffset += partRealLen;\n\t\t\t}\n\t\t}\n\t}\n\n\tflushGroup();\n\n\treturn result;\n}\n","// biome-ignore format: matrix\nexport type Matrix4 = [\n\tnumber, number, number, number,\n\tnumber, number, number, number,\n\tnumber, number, number, number,\n\tnumber, number, number, number,\n];\n\nexport function createMatrix4(): Matrix4 {\n\t// biome-ignore format: matrix\n\treturn [\n 1, 0, 0, 0,\n 0, 1, 0, 0,\n 0, 0, 1, 0,\n 0, 0, 0, 1\n ];\n}\n\nexport function scaleMatrix4(\n\tm: Matrix4,\n\tscale = 1,\n\torigin = { x: 0, y: 0 },\n): Matrix4 {\n\tconst [ox, oy] = [origin.x, origin.y];\n\t// biome-ignore format: matrix\n\treturn [\n m[0] * scale , m[1] * scale , m[2] * scale , m[3],\n m[4] * scale , m[5] * scale , m[6] * scale , m[7],\n m[8] * scale , m[9] * scale , m[10] * scale, m[11],\n m[12] - ox * scale + ox, m[13] - oy * scale + oy, m[14] , m[15]\n ];\n}\n\nexport function translateMatrix4(m: Matrix4, x = 0, y = 0, z = 0): Matrix4 {\n\t// biome-ignore format: matrix\n\treturn [\n m[0] , m[1] , m[2] , m[3] ,\n m[4] , m[5] , m[6] , m[7] ,\n m[8] , m[9] , m[10] , m[11],\n m[12] + x, m[13] + y, m[14] + z, m[15]\n ];\n}\n\nexport function matrix4ToCSS(m: Matrix4, fractionDigits = 4): string {\n\tconst format = (n: number, _: number) => n.toFixed(fractionDigits);\n\treturn `matrix3d(${m.map(format).join(\", \")})`;\n}\n","import bezier from \"bezier-easing\";\nimport type { LyricLine, LyricWord } from \"#interfaces\";\nimport { LyricLineRenderMode } from \"#lyric/base/consts.ts\";\nimport { LyricLineBase } from \"#lyric/base/line.ts\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { clamp, clamp01, clampPositive } from \"#utils/clamp.ts\";\nimport { isCJK } from \"#utils/is-cjk.ts\";\nimport { LineBalancer } from \"#utils/line-balancer.ts\";\nimport { chunkAndSplitLyricWords } from \"#utils/lyric-split-words.ts\";\nimport { createMatrix4, matrix4ToCSS, scaleMatrix4 } from \"#utils/matrix.ts\";\nimport type { DomLyricPlayer } from \".\";\n\ninterface RealWord extends LyricWord {\n\tmainElement: HTMLSpanElement;\n\tsubElements: HTMLSpanElement[];\n\telementAnimations: Animation[];\n\tmaskAnimations: Animation[];\n\twidth: number;\n\theight: number;\n\tpadding: number;\n\tshouldEmphasize: boolean;\n}\n\nconst ANIMATION_FRAME_QUANTITY = 32;\n\nconst norNum = (min: number, max: number) => (x: number) =>\n\tclamp01((x - min) / (max - min));\nconst EMP_EASING_MID = 0.5;\nconst beginNum = norNum(0, EMP_EASING_MID);\nconst endNum = norNum(EMP_EASING_MID, 1);\n\nconst bezIn = bezier(0.2, 0.4, 0.58, 1.0);\nconst bezOut = bezier(0.3, 0.0, 0.58, 1.0);\n\nconst makeEmpEasing = (mid: number) => {\n\treturn (x: number) => (x < mid ? bezIn(beginNum(x)) : 1 - bezOut(endNum(x)));\n};\n\nfunction generateFadeGradient(\n\twidth: number,\n\tpadding = 0,\n\tbright = \"rgba(0,0,0,var(--bright-mask-alpha, 1.0))\",\n\tdark = \"rgba(0,0,0,var(--dark-mask-alpha, 1.0))\",\n): [string, number] {\n\tconst totalAspect = 2 + width + padding;\n\tconst widthInTotal = width / totalAspect;\n\tconst leftPos = (1 - widthInTotal) / 2;\n\treturn [\n\t\t`linear-gradient(to right,${bright} ${leftPos * 100}%,${dark} ${\n\t\t\t(leftPos + widthInTotal) * 100\n\t\t}%)`,\n\t\ttotalAspect,\n\t];\n}\n\nexport class RawLyricLineMouseEvent extends MouseEvent {\n\tconstructor(\n\t\tpublic readonly line: LyricLineBase,\n\t\tevent: MouseEvent,\n\t) {\n\t\tsuper(event.type, event);\n\t}\n}\n\ntype MouseEventMap = {\n\t[evt in keyof HTMLElementEventMap]: HTMLElementEventMap[evt] extends MouseEvent\n\t\t? evt\n\t\t: never;\n};\ntype MouseEventTypes = MouseEventMap[keyof MouseEventMap];\ntype MouseEventListener = (\n\tthis: LyricLineEl,\n\tev: RawLyricLineMouseEvent,\n) => void;\n\nexport class LyricLineEl extends LyricLineBase {\n\tprivate element: HTMLElement = document.createElement(\"div\");\n\tprivate splittedWords: RealWord[] = [];\n\t// 标记是否已经构建了行内的实际 DOM(单词与动画等)\n\tprivate built = false;\n\n\t// 由 LyricPlayer 来设置\n\tlineSize: number[] = [0, 0];\n\n\tprivate renderMode: LyricLineRenderMode = LyricLineRenderMode.SOLID;\n\n\tprivate currentBrightAlpha = 1.0;\n\tprivate currentDarkAlpha = 0.2;\n\n\tprivate targetBrightAlpha = 1.0;\n\tprivate targetDarkAlpha = 0.2;\n\n\t/**\n\t * 用于平衡换行、尽量减少各行长度差异的类\n\t */\n\tprivate balancer?: LineBalancer;\n\n\tconstructor(\n\t\tprivate lyricPlayer: DomLyricPlayer,\n\t\tprivate lyricLine: LyricLine = {\n\t\t\twords: [],\n\t\t\ttranslatedLyric: \"\",\n\t\t\tromanLyric: \"\",\n\t\t\tstartTime: 0,\n\t\t\tendTime: 0,\n\t\t\tisBG: false,\n\t\t\tisDuet: false,\n\t\t},\n\t) {\n\t\tsuper();\n\t\tthis.element.setAttribute(\"class\", styles.lyricLine);\n\t\tif (this.lyricLine.isBG) {\n\t\t\tthis.element.classList.add(styles.lyricBgLine);\n\t\t}\n\t\tif (this.lyricLine.isDuet) {\n\t\t\tthis.element.classList.add(styles.lyricDuetLine);\n\t\t}\n\t\tthis.element.appendChild(document.createElement(\"div\")); // 歌词行\n\t\tthis.element.appendChild(document.createElement(\"div\")); // 翻译行\n\t\tthis.element.appendChild(document.createElement(\"div\")); // 音译行\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\t\tconst trans = this.element.children[1] as HTMLDivElement;\n\t\tconst roman = this.element.children[2] as HTMLDivElement;\n\t\tmain.setAttribute(\"class\", styles.lyricMainLine);\n\t\ttrans.setAttribute(\"class\", styles.lyricSubLine);\n\t\troman.setAttribute(\"class\", styles.lyricSubLine);\n\t\tif (LyricLineBase.wordSegmenter) {\n\t\t\tthis.balancer = new LineBalancer(main);\n\t\t}\n\t\t// 延迟构建具体行内容,进入可视区(含 overscan)时再构建\n\t\tthis.rebuildStyle();\n\t}\n\tprivate listenersMap = new Map<string, Set<MouseEventListener>>();\n\tprivate readonly onMouseEvent = (e: MouseEvent) => {\n\t\tconst wrapped = new RawLyricLineMouseEvent(this, e);\n\t\tfor (const listener of this.listenersMap.get(e.type) ?? []) {\n\t\t\tlistener.call(this, wrapped);\n\t\t}\n\t\tif (!this.dispatchEvent(wrapped) || wrapped.defaultPrevented) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\t};\n\n\taddMouseEventListener(\n\t\ttype: MouseEventTypes,\n\t\tcallback: MouseEventListener | null,\n\t\toptions?: boolean | AddEventListenerOptions | undefined,\n\t): void {\n\t\tif (callback) {\n\t\t\tconst listeners = this.listenersMap.get(type) ?? new Set();\n\t\t\tif (listeners.size === 0)\n\t\t\t\tthis.element.addEventListener(type, this.onMouseEvent, options);\n\t\t\tlisteners.add(callback);\n\t\t\tthis.listenersMap.set(type, listeners);\n\t\t}\n\t}\n\n\tremoveMouseEventListener(\n\t\ttype: MouseEventTypes,\n\t\tcallback: MouseEventListener | null,\n\t\toptions?: boolean | EventListenerOptions | undefined,\n\t): void {\n\t\tif (callback) {\n\t\t\tconst listeners = this.listenersMap.get(type);\n\t\t\tif (listeners) {\n\t\t\t\tlisteners.delete(callback);\n\t\t\t\tif (listeners.size === 0)\n\t\t\t\t\tthis.element.removeEventListener(type, this.onMouseEvent, options);\n\t\t\t}\n\t\t}\n\t}\n\n\tareWordsOnSameLine(word1: RealWord, word2: RealWord): boolean {\n\t\tif (word1?.mainElement && word2?.mainElement) {\n\t\t\tconst word1el = word1.mainElement;\n\t\t\tconst word2el = word2.mainElement;\n\n\t\t\tconst rect1 = word1el.getBoundingClientRect();\n\t\t\tconst rect2 = word2el.getBoundingClientRect();\n\n\t\t\t// 检查两个单词的顶部距离是否相等(或者差值很小)\n\t\t\tconst topDifference = Math.abs(rect1.top - rect2.top);\n\n\t\t\t// 如果顶部距离相差很小,可以认为它们在同一行上\n\t\t\treturn topDifference < 10;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate isEnabled = false;\n\tasync enable(\n\t\tmaskAnimationTime: number = this.lyricPlayer.getCurrentTime(),\n\t\tshouldPlay: boolean = this.lyricPlayer.getIsPlaying(),\n\t): Promise<void> {\n\t\tthis.isEnabled = true;\n\t\tthis.element.classList.add(styles.active);\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\n\t\tconst relativeTime = clampPositive(\n\t\t\tmaskAnimationTime - this.lyricLine.startTime,\n\t\t);\n\n\t\tfor (const word of this.splittedWords) {\n\t\t\tfor (const a of word.elementAnimations) {\n\t\t\t\ta.currentTime = relativeTime;\n\t\t\t\ta.playbackRate = 1;\n\n\t\t\t\tconst timing = a.effect?.getComputedTiming();\n\t\t\t\tconst duration = Number(timing?.duration ?? 0);\n\t\t\t\tconst delay = Number(timing?.delay ?? 0);\n\t\t\t\tconst endTime = delay + duration;\n\n\t\t\t\tif (shouldPlay && relativeTime < endTime) a.play();\n\t\t\t\telse a.pause();\n\t\t\t}\n\n\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\tconst t = Math.min(this.totalDuration, relativeTime);\n\t\t\t\ta.currentTime = t;\n\t\t\t\ta.playbackRate = 1;\n\n\t\t\t\tconst timing = a.effect?.getComputedTiming();\n\t\t\t\tconst duration = Number(timing?.duration ?? 0);\n\t\t\t\tconst delay = Number(timing?.delay ?? 0);\n\t\t\t\tconst endTime = delay + duration;\n\n\t\t\t\tif (shouldPlay && t < endTime) a.play();\n\t\t\t\telse a.pause();\n\t\t\t}\n\t\t}\n\t\tmain.classList.add(styles.active);\n\t}\n\n\tdisable(): void {\n\t\tthis.isEnabled = false;\n\t\tthis.element.classList.remove(styles.active);\n\t\tthis.renderMode = LyricLineRenderMode.SOLID;\n\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\n\t\tfor (const word of this.splittedWords) {\n\t\t\tfor (const a of word.elementAnimations) {\n\t\t\t\tif (\n\t\t\t\t\ta.id === \"float-word\" ||\n\t\t\t\t\ta.id.includes(\"emphasize-word-float-only\")\n\t\t\t\t) {\n\t\t\t\t\ta.playbackRate = -1;\n\t\t\t\t\ta.play();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\ta.pause();\n\t\t\t}\n\t\t}\n\t\tmain.classList.remove(styles.active);\n\t}\n\n\tprivate lastWord?: RealWord;\n\n\tasync resume(): Promise<void> {\n\t\tif (!this.isEnabled) return;\n\t\tfor (const word of this.splittedWords) {\n\t\t\tfor (const a of word.elementAnimations) {\n\t\t\t\tif (\n\t\t\t\t\t!this.lastWord ||\n\t\t\t\t\tthis.splittedWords.indexOf(this.lastWord) <\n\t\t\t\t\t\tthis.splittedWords.indexOf(word)\n\t\t\t\t) {\n\t\t\t\t\tconst timing = a.effect?.getComputedTiming();\n\t\t\t\t\tconst duration = (timing?.duration as number) || 0;\n\t\t\t\t\tconst delay = (timing?.delay as number) || 0;\n\t\t\t\t\tconst endTime = delay + duration;\n\t\t\t\t\tconst currentTime = (a.currentTime as number) || 0;\n\n\t\t\t\t\tif (a.playState !== \"finished\" && currentTime < endTime) {\n\t\t\t\t\t\ta.play();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\tif (\n\t\t\t\t\t!this.lastWord ||\n\t\t\t\t\tthis.splittedWords.indexOf(this.lastWord) <\n\t\t\t\t\t\tthis.splittedWords.indexOf(word)\n\t\t\t\t) {\n\t\t\t\t\tconst timing = a.effect?.getComputedTiming();\n\t\t\t\t\tconst duration = (timing?.duration as number) || 0;\n\t\t\t\t\tconst delay = (timing?.delay as number) || 0;\n\t\t\t\t\tconst endTime = delay + duration;\n\n\t\t\t\t\tconst currentTime = (a.currentTime as number) || 0;\n\n\t\t\t\t\tif (a.playState !== \"finished\" && currentTime < endTime) {\n\t\t\t\t\t\ta.play();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tif (!this.isEnabled) return;\n\t\tfor (const word of this.splittedWords) {\n\t\t\tfor (const a of word.elementAnimations) {\n\t\t\t\ta.pause();\n\t\t\t}\n\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\ta.pause();\n\t\t\t}\n\t\t}\n\t}\n\tsetMaskAnimationState(maskAnimationTime = 0): void {\n\t\tconst t = maskAnimationTime - this.lyricLine.startTime;\n\t\tfor (const word of this.splittedWords) {\n\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\ta.currentTime = clamp(t, 0, this.totalDuration);\n\t\t\t\ta.playbackRate = 1;\n\t\t\t\tif (t >= 0 && t < this.totalDuration) a.play();\n\t\t\t\telse a.pause();\n\t\t\t}\n\t\t}\n\t}\n\n\tgetLine(): LyricLine {\n\t\treturn this.lyricLine;\n\t}\n\t// private _hide = true;\n\tprivate lastStyle = \"\";\n\tshow(): void {\n\t\tif (!this.built) {\n\t\t\tthis.rebuildElement();\n\t\t\tthis.built = true;\n\t\t\tthis.updateMaskImageSync();\n\t\t}\n\t}\n\n\tprivate rebuildStyle() {\n\t\tlet style = \"\";\n\t\tstyle += `transform: scale(${(this.lineTransforms.scale.getCurrentPosition() / 100).toFixed(4)});`;\n\n\t\tif (!this.lyricPlayer.getEnableSpring()) {\n\t\t\tstyle += `transition-delay:${this.delay}ms;`;\n\t\t}\n\n\t\tstyle += `filter:blur(${Math.min(5, this.blur)}px);`;\n\t\tif (style !== this.lastStyle) {\n\t\t\tthis.lastStyle = style;\n\t\t\tthis.element.setAttribute(\"style\", style);\n\t\t}\n\t}\n\n\toverride rebuildElement(): void {\n\t\tthis.disposeElements();\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\t\tconst trans = this.element.children[1] as HTMLDivElement;\n\t\tconst roman = this.element.children[2] as HTMLDivElement;\n\t\t// 非动态歌词,直接渲染整行与副行\n\t\tif (this.lyricPlayer._getIsNonDynamic()) {\n\t\t\tmain.innerText = this.lyricLine.words\n\t\t\t\t.map((w) => this.lyricPlayer.processObsceneWord(w))\n\t\t\t\t.join(\"\");\n\t\t\tthis.setSubLinesText(trans, roman);\n\t\t\treturn;\n\t\t}\n\n\t\tconst chunkedWords = chunkAndSplitLyricWords(this.lyricLine.words);\n\t\tconst hasRubyLine = this.lyricLine.words.some(\n\t\t\t(word) => (word.ruby?.length ?? 0) > 0,\n\t\t);\n\t\tconst hasRomanLine = this.lyricLine.words.some(\n\t\t\t(word) => (word.romanWord?.trim().length ?? 0) > 0,\n\t\t);\n\t\tmain.innerHTML = \"\";\n\n\t\tfor (const chunk of chunkedWords) {\n\t\t\tthis.buildWord(chunk, main, hasRubyLine, hasRomanLine);\n\t\t}\n\n\t\tthis.setSubLinesText(trans, roman);\n\t}\n\n\t/** 设置翻译与音译行文本 */\n\tprivate setSubLinesText(trans: HTMLDivElement, roman: HTMLDivElement) {\n\t\ttrans.innerText = this.lyricLine.translatedLyric;\n\t\troman.innerText = this.lyricLine.romanLyric;\n\t}\n\n\tprivate getRubyCharCount(word: LyricWord) {\n\t\treturn (word.ruby ?? []).reduce(\n\t\t\t(total, ruby) => total + ruby.word.length,\n\t\t\t0,\n\t\t);\n\t}\n\n\tprivate getRubySegments(word: LyricWord) {\n\t\treturn (word.ruby ?? []).filter(\n\t\t\t(ruby) => (ruby?.word?.trim().length ?? 0) > 0,\n\t\t);\n\t}\n\n\tprivate createWord(\n\t\tword: LyricWord,\n\t\tshouldEmphasize: boolean,\n\t\thasRubyLine: boolean,\n\t\thasRomanLine: boolean,\n\t): RealWord {\n\t\tconst mainWordEl = document.createElement(\"span\");\n\t\tconst subElements: HTMLSpanElement[] = [];\n\t\tconst romanWord = word.romanWord?.trim() ?? \"\";\n\t\tconst wordContainer = hasRubyLine\n\t\t\t? document.createElement(\"div\")\n\t\t\t: mainWordEl;\n\n\t\tif (hasRubyLine) {\n\t\t\tconst rubyWordEl = document.createElement(\"div\");\n\t\t\tconst rubySegments = this.getRubySegments(word);\n\t\t\tfor (const ruby of rubySegments) {\n\t\t\t\tconst rubyPartEl = document.createElement(\"span\");\n\t\t\t\trubyPartEl.innerText = ruby.word;\n\t\t\t\trubyPartEl.dataset.startTime = String(ruby.startTime);\n\t\t\t\trubyPartEl.dataset.endTime = String(ruby.endTime);\n\t\t\t\trubyWordEl.appendChild(rubyPartEl);\n\t\t\t}\n\t\t\trubyWordEl.classList.add(styles.rubyWord);\n\t\t\tmainWordEl.classList.add(styles.wordWithRuby);\n\t\t\twordContainer.classList.add(styles.wordBody);\n\t\t\tmainWordEl.appendChild(rubyWordEl);\n\t\t\tmainWordEl.appendChild(wordContainer);\n\t\t}\n\n\t\tconst displayWord = this.lyricPlayer.processObsceneWord(word);\n\n\t\tif (shouldEmphasize) {\n\t\t\tmainWordEl.classList.add(styles.emphasize);\n\t\t\tconst trimmedWord = displayWord.trim();\n\n\t\t\tif (LyricLineBase.graphemeSegmenter) {\n\t\t\t\tfor (const { segment } of LyricLineBase.graphemeSegmenter.segment(\n\t\t\t\t\ttrimmedWord,\n\t\t\t\t)) {\n\t\t\t\t\tconst charEl = document.createElement(\"span\");\n\t\t\t\t\tcharEl.innerText = segment;\n\t\t\t\t\tsubElements.push(charEl);\n\t\t\t\t\twordContainer.appendChild(charEl);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (const segment of Array.from(trimmedWord)) {\n\t\t\t\t\tconst charEl = document.createElement(\"span\");\n\t\t\t\t\tcharEl.innerText = segment;\n\t\t\t\t\tsubElements.push(charEl);\n\t\t\t\t\twordContainer.appendChild(charEl);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (hasRomanLine) {\n\t\t\t\tconst wordEl = document.createElement(\"div\");\n\t\t\t\twordEl.innerText = displayWord.trim();\n\t\t\t\twordContainer.appendChild(wordEl);\n\t\t\t} else if (romanWord.length === 0) {\n\t\t\t\twordContainer.innerText = displayWord.trim();\n\t\t\t}\n\t\t}\n\n\t\tif (hasRomanLine) {\n\t\t\tconst romanWordEl = document.createElement(\"div\");\n\t\t\tromanWordEl.innerText = romanWord.length > 0 ? romanWord : \"\\u00A0\";\n\t\t\tromanWordEl.classList.add(styles.romanWord);\n\t\t\twordContainer.appendChild(romanWordEl);\n\t\t}\n\n\t\tconst realWord: RealWord = {\n\t\t\t...word,\n\t\t\tmainElement: mainWordEl,\n\t\t\tsubElements: subElements,\n\t\t\telementAnimations: [this.initFloatAnimation(word, mainWordEl)],\n\t\t\tmaskAnimations: [],\n\t\t\twidth: 0,\n\t\t\theight: 0,\n\t\t\tpadding: 0,\n\t\t\tshouldEmphasize: shouldEmphasize,\n\t\t};\n\n\t\treturn realWord;\n\t}\n\n\tprivate buildWord(\n\t\tinput: LyricWord | LyricWord[],\n\t\tmain: HTMLDivElement,\n\t\thasRubyLine: boolean,\n\t\thasRomanLine: boolean,\n\t) {\n\t\tconst chunk = Array.isArray(input) ? input : [input];\n\t\tif (chunk.length === 0) return;\n\n\t\tconst isPureSpace = chunk.every((w) => !w.word.trim());\n\t\tif (isPureSpace) {\n\t\t\tconst textContent = chunk.map((w) => w.word).join(\"\");\n\t\t\tmain.appendChild(document.createTextNode(textContent));\n\t\t\treturn;\n\t\t}\n\n\t\tconst merged = chunk.reduce(\n\t\t\t(a, b) => {\n\t\t\t\ta.endTime = Math.max(a.endTime, b.endTime);\n\t\t\t\ta.startTime = Math.min(a.startTime, b.startTime);\n\t\t\t\ta.word += b.word;\n\t\t\t\treturn a;\n\t\t\t},\n\t\t\t{\n\t\t\t\tword: \"\",\n\t\t\t\tromanWord: \"\",\n\t\t\t\tstartTime: Number.POSITIVE_INFINITY,\n\t\t\t\tendTime: Number.NEGATIVE_INFINITY,\n\t\t\t\twordType: \"normal\",\n\t\t\t\tobscene: false,\n\t\t\t} as LyricWord,\n\t\t);\n\n\t\tlet emp = chunk.some((word) => LyricLineBase.shouldEmphasize(word));\n\t\tif (!isCJK(merged.word)) {\n\t\t\temp = emp || LyricLineBase.shouldEmphasize(merged);\n\t\t}\n\n\t\tconst wrapperWordEl = document.createElement(\"span\");\n\t\twrapperWordEl.classList.add(styles.emphasizeWrapper);\n\n\t\tconst characterElements: HTMLElement[] = [];\n\n\t\tfor (const word of chunk) {\n\t\t\tif (!word.word.trim()) {\n\t\t\t\twrapperWordEl.appendChild(document.createTextNode(word.word));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst realWord = this.createWord(word, emp, hasRubyLine, hasRomanLine);\n\n\t\t\tif (emp) {\n\t\t\t\tcharacterElements.push(...realWord.subElements);\n\t\t\t}\n\n\t\t\tthis.splittedWords.push(realWord);\n\t\t\twrapperWordEl.appendChild(realWord.mainElement);\n\t\t}\n\n\t\tif (emp && this.splittedWords.length > 0) {\n\t\t\tconst lastWordOfChunk = this.splittedWords[this.splittedWords.length - 1];\n\t\t\tconst rubyCharCount = chunk.reduce(\n\t\t\t\t(total, word) => total + this.getRubyCharCount(word),\n\t\t\t\t0,\n\t\t\t);\n\n\t\t\tlastWordOfChunk.elementAnimations.push(\n\t\t\t\t...this.initEmphasizeAnimation(\n\t\t\t\t\tmerged,\n\t\t\t\t\tcharacterElements,\n\t\t\t\t\tmerged.endTime - merged.startTime,\n\t\t\t\t\tmerged.startTime - this.lyricLine.startTime,\n\t\t\t\t\trubyCharCount,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tmain.appendChild(wrapperWordEl);\n\t}\n\n\tprivate initFloatAnimation(word: LyricWord, wordEl: HTMLSpanElement) {\n\t\tconst delay = word.startTime - this.lyricLine.startTime;\n\t\tconst duration = Math.max(1000, word.endTime - word.startTime);\n\t\tlet up = 0.05;\n\t\tif (this.lyricLine.isBG) {\n\t\t\tup *= 2;\n\t\t}\n\t\tconst a = wordEl.animate(\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\ttransform: \"translateY(0px)\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttransform: `translateY(${-up}em)`,\n\t\t\t\t},\n\t\t\t],\n\t\t\t{\n\t\t\t\tduration: Number.isFinite(duration) ? duration : 0,\n\t\t\t\tdelay: Number.isFinite(delay) ? delay : 0,\n\t\t\t\tid: \"float-word\",\n\t\t\t\tcomposite: \"add\",\n\t\t\t\tfill: \"both\",\n\t\t\t\teasing: \"ease-out\",\n\t\t\t},\n\t\t);\n\t\ta.pause();\n\t\treturn a;\n\t}\n\t// 按照原 Apple Music 参考,强调效果只应用缩放、轻微左右位移和辉光效果,原主要的悬浮位移效果不变\n\t// 为了避免产生锯齿抖动感,使用 matrix3d 来实现缩放和位移\n\tprivate initEmphasizeAnimation(\n\t\tword: LyricWord,\n\t\tcharacterElements: HTMLElement[],\n\t\tduration: number,\n\t\tdelay: number,\n\t\trubyCharCount: number,\n\t): Animation[] {\n\t\tconst de = clampPositive(delay);\n\t\tlet du = Math.max(1000, duration);\n\t\tconst anchorCharCount =\n\t\t\trubyCharCount > 0 ? rubyCharCount : Math.max(1, characterElements.length);\n\n\t\tlet result: Animation[] = [];\n\n\t\tlet amount = du / 2000;\n\t\tamount = amount > 1 ? Math.sqrt(amount) : amount ** 3;\n\t\tlet blur = du / 3000;\n\t\tblur = blur > 1 ? Math.sqrt(blur) : blur ** 3;\n\t\tamount *= 0.6;\n\t\tblur *= 0.5;\n\t\tif (\n\t\t\tthis.lyricLine.words.length > 0 &&\n\t\t\tword.word.includes(\n\t\t\t\tthis.lyricLine.words[this.lyricLine.words.length - 1].word,\n\t\t\t)\n\t\t) {\n\t\t\tamount *= 1.6;\n\t\t\tblur *= 1.5;\n\t\t\tdu *= 1.2;\n\t\t}\n\t\tamount = Math.min(1.2, amount);\n\t\tblur = Math.min(0.8, blur);\n\n\t\tconst animateDu = Number.isFinite(du) ? du : 0;\n\t\tconst empEasing = makeEmpEasing(EMP_EASING_MID);\n\n\t\tresult = characterElements.flatMap((el, i, arr) => {\n\t\t\tconst wordDe = de + (du / 2.5 / anchorCharCount) * i;\n\t\t\tconst result: Animation[] = [];\n\n\t\t\tconst frames: Keyframe[] = new Array(ANIMATION_FRAME_QUANTITY)\n\t\t\t\t.fill(0)\n\t\t\t\t.map((_, j) => {\n\t\t\t\t\tconst x = (j + 1) / ANIMATION_FRAME_QUANTITY;\n\t\t\t\t\tconst transX = empEasing(x);\n\t\t\t\t\tconst glowLevel = empEasing(x) * blur;\n\n\t\t\t\t\tconst mat = scaleMatrix4(createMatrix4(), 1 + transX * 0.1 * amount);\n\t\t\t\t\tconst offsetX = -transX * 0.03 * amount * (arr.length / 2 - i);\n\t\t\t\t\tconst offsetY = -transX * 0.025 * amount;\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\toffset: x,\n\t\t\t\t\t\ttransform: `${matrix4ToCSS(\n\t\t\t\t\t\t\tmat,\n\t\t\t\t\t\t\t4,\n\t\t\t\t\t\t)} translate(${offsetX}em, ${offsetY}em)`,\n\t\t\t\t\t\ttextShadow: `0 0 ${Math.min(\n\t\t\t\t\t\t\t0.3,\n\t\t\t\t\t\t\tblur * 0.3,\n\t\t\t\t\t\t)}em rgba(255, 255, 255, ${glowLevel})`,\n\t\t\t\t\t};\n\t\t\t\t});\n\n\t\t\tconst glow = el.animate(frames, {\n\t\t\t\tduration: animateDu,\n\t\t\t\tdelay: Number.isFinite(wordDe) ? wordDe : 0,\n\t\t\t\tid: `emphasize-word-${el.innerText}-${i}`,\n\t\t\t\titerations: 1,\n\t\t\t\tcomposite: \"replace\",\n\t\t\t\tfill: \"both\",\n\t\t\t});\n\t\t\tglow.onfinish = () => {\n\t\t\t\tglow.pause();\n\t\t\t};\n\t\t\tglow.pause();\n\t\t\tresult.push(glow);\n\n\t\t\tconst floatFrame: Keyframe[] = new Array(ANIMATION_FRAME_QUANTITY)\n\t\t\t\t.fill(0)\n\t\t\t\t.map((_, j) => {\n\t\t\t\t\tconst x = (j + 1) / ANIMATION_FRAME_QUANTITY;\n\t\t\t\t\tlet y = Math.sin(x * Math.PI);\n\t\t\t\t\t// y = x < 0.5 ? y : Math.max(y, 1.0);\n\t\t\t\t\tif (this.lyricLine.isBG) {\n\t\t\t\t\t\ty *= 2;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\toffset: x,\n\t\t\t\t\t\ttransform: `translateY(${-y * 0.05}em)`,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\tconst float = el.animate(floatFrame, {\n\t\t\t\tduration: animateDu * 1.4,\n\t\t\t\tdelay: Number.isFinite(wordDe) ? wordDe - 400 : 0,\n\t\t\t\tid: \"emphasize-word-float\",\n\t\t\t\titerations: 1,\n\t\t\t\tcomposite: \"add\",\n\t\t\t\tfill: \"both\",\n\t\t\t});\n\t\t\tfloat.onfinish = () => {\n\t\t\t\tfloat.pause();\n\t\t\t};\n\t\t\tfloat.pause();\n\t\t\tresult.push(float);\n\n\t\t\treturn result;\n\t\t});\n\n\t\treturn result;\n\t}\n\n\tprivate get totalDuration() {\n\t\treturn this.lyricLine.endTime - this.lyricLine.startTime;\n\t}\n\n\toverride onLineSizeChange(_size: [number, number]): void {\n\t\tthis.updateMaskImageSync();\n\t}\n\tupdateMaskImageSync(): void {\n\t\tfor (const word of this.splittedWords) {\n\t\t\tconst el = word.mainElement;\n\t\t\tif (el) {\n\t\t\t\tword.padding = Number.parseFloat(getComputedStyle(el).paddingLeft);\n\t\t\t\tword.width = el.clientWidth - word.padding * 2;\n\t\t\t\tword.height = el.clientHeight - word.padding * 2;\n\t\t\t} else {\n\t\t\t\tword.width = 0;\n\t\t\t\tword.height = 0;\n\t\t\t\tword.padding = 0;\n\t\t\t}\n\t\t}\n\t\tif (this.balancer && LyricLineBase.wordSegmenter) {\n\t\t\tthis.balancer.balanceLineBreaks(\n\t\t\t\tthis.lyricPlayer._getIsNonDynamic(),\n\t\t\t\tthis.splittedWords.length > 0,\n\t\t\t\tLyricLineBase.wordSegmenter,\n\t\t\t);\n\t\t}\n\t\tif (this.lyricPlayer.supportMaskImage) {\n\t\t\tthis.generateWebAnimationBasedMaskImage();\n\t\t} else {\n\t\t\tthis.generateCalcBasedMaskImage();\n\t\t}\n\t\tif (this.isEnabled) {\n\t\t\tconst isPlayerRunning = this.lyricPlayer.getIsPlaying?.() ?? true;\n\t\t\tthis.enable(this.lyricPlayer.getCurrentTime(), isPlayerRunning);\n\t\t}\n\t}\n\n\tprivate generateCalcBasedMaskImage() {\n\t\tfor (const word of this.splittedWords) {\n\t\t\tconst wordEl = word.mainElement;\n\t\t\tif (wordEl) {\n\t\t\t\tword.width = wordEl.clientWidth;\n\t\t\t\tword.height = wordEl.clientHeight;\n\t\t\t\tconst fadeWidth = word.height * this.lyricPlayer.getWordFadeWidth();\n\t\t\t\tconst [maskImage, totalAspect] = generateFadeGradient(\n\t\t\t\t\tfadeWidth / word.width,\n\t\t\t\t);\n\t\t\t\tconst totalAspectStr = `${totalAspect * 100}% 100%`;\n\t\t\t\tif (this.lyricPlayer.supportMaskImage) {\n\t\t\t\t\twordEl.style.maskImage = maskImage;\n\t\t\t\t\twordEl.style.maskRepeat = \"no-repeat\";\n\t\t\t\t\twordEl.style.maskOrigin = \"left\";\n\t\t\t\t\twordEl.style.maskSize = totalAspectStr;\n\t\t\t\t} else {\n\t\t\t\t\twordEl.style.webkitMaskImage = maskImage;\n\t\t\t\t\twordEl.style.webkitMaskRepeat = \"no-repeat\";\n\t\t\t\t\twordEl.style.webkitMaskOrigin = \"left\";\n\t\t\t\t\twordEl.style.webkitMaskSize = totalAspectStr;\n\t\t\t\t}\n\t\t\t\tconst w = word.width + fadeWidth;\n\t\t\t\tconst maskPos = `clamp(${-w}px,calc(${-w}px + (var(--amll-player-time) - ${\n\t\t\t\t\tword.startTime\n\t\t\t\t})*${\n\t\t\t\t\tw / Math.abs(word.endTime - word.startTime)\n\t\t\t\t}px),0px) 0px, left top`;\n\t\t\t\twordEl.style.maskPosition = maskPos;\n\t\t\t\twordEl.style.webkitMaskPosition = maskPos;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate generateWebAnimationBasedMaskImage() {\n\t\t// 因为歌词行有可能比行内单词的结束时间早,有可能导致过渡动画提早停止出现瑕疵\n\t\t// 所以要以单词的结束时间为准\n\t\tconst totalFadeDuration =\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\t...this.splittedWords.map((w) => w.endTime),\n\t\t\t\tthis.lyricLine.endTime,\n\t\t\t) - this.lyricLine.startTime;\n\t\tthis.splittedWords.forEach((word, i) => {\n\t\t\tconst wordEl = word.mainElement;\n\t\t\tif (wordEl) {\n\t\t\t\tconst fadeWidth = word.height * this.lyricPlayer.getWordFadeWidth();\n\t\t\t\tconst [maskImage, totalAspect] = generateFadeGradient(\n\t\t\t\t\tfadeWidth / (word.width + word.padding * 2),\n\t\t\t\t);\n\t\t\t\tconst totalAspectStr = `${totalAspect * 100}% 100%`;\n\t\t\t\tif (this.lyricPlayer.supportMaskImage) {\n\t\t\t\t\twordEl.style.maskImage = maskImage;\n\t\t\t\t\twordEl.style.maskRepeat = \"no-repeat\";\n\t\t\t\t\twordEl.style.maskOrigin = \"left\";\n\t\t\t\t\twordEl.style.maskSize = totalAspectStr;\n\t\t\t\t} else {\n\t\t\t\t\twordEl.style.webkitMaskImage = maskImage;\n\t\t\t\t\twordEl.style.webkitMaskRepeat = \"no-repeat\";\n\t\t\t\t\twordEl.style.webkitMaskOrigin = \"left\";\n\t\t\t\t\twordEl.style.webkitMaskSize = totalAspectStr;\n\t\t\t\t}\n\t\t\t\t// 为了尽可能将渐变动画在相连的每个单词间近似衔接起来\n\t\t\t\t// 要综合每个单词的效果时间和间隙生成动画帧数组\n\t\t\t\tconst widthBeforeSelf =\n\t\t\t\t\tthis.splittedWords.slice(0, i).reduce((a, b) => a + b.width, 0) +\n\t\t\t\t\t(this.splittedWords[0] ? fadeWidth : 0);\n\t\t\t\tconst minOffset = -(word.width + word.padding * 2 + fadeWidth);\n\t\t\t\tconst clampOffset = (x: number) => clamp(x, minOffset, 0);\n\t\t\t\tlet curPos = -widthBeforeSelf - word.width - word.padding - fadeWidth;\n\t\t\t\tlet timeOffset = 0;\n\t\t\t\tconst frames: Keyframe[] = [];\n\t\t\t\tlet lastPos = curPos;\n\t\t\t\tlet lastTime = 0;\n\t\t\t\tconst pushFrame = () => {\n\t\t\t\t\t// 此处如果添加过渡函数,会导致单词时序不准确,所以不添加\n\t\t\t\t\t// const easing = \"cubic-bezier(.33,.12,.83,.9)\";\n\t\t\t\t\tconst moveOffset = curPos - lastPos;\n\t\t\t\t\tconst time = clamp01(timeOffset);\n\t\t\t\t\tconst duration = time - lastTime;\n\t\t\t\t\tconst d = Math.abs(duration / moveOffset);\n\t\t\t\t\t// 因为有可能会和之前的动画有边界\n\t\t\t\t\tif (curPos > minOffset && lastPos < minOffset) {\n\t\t\t\t\t\tconst staticTime = Math.abs(lastPos - minOffset) * d;\n\t\t\t\t\t\tconst value = `${clampOffset(lastPos)}px 0`;\n\t\t\t\t\t\tconst frame: Keyframe = {\n\t\t\t\t\t\t\toffset: lastTime + staticTime,\n\t\t\t\t\t\t\tmaskPosition: value,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tframes.push(frame);\n\t\t\t\t\t}\n\t\t\t\t\tif (curPos > 0 && lastPos < 0) {\n\t\t\t\t\t\tconst staticTime = Math.abs(lastPos) * d;\n\t\t\t\t\t\tconst value = `${clampOffset(curPos)}px 0`;\n\t\t\t\t\t\tconst frame: Keyframe = {\n\t\t\t\t\t\t\toffset: lastTime + staticTime,\n\t\t\t\t\t\t\tmaskPosition: value,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tframes.push(frame);\n\t\t\t\t\t}\n\t\t\t\t\tconst value = `${clampOffset(curPos)}px 0`;\n\t\t\t\t\tconst frame: Keyframe = {\n\t\t\t\t\t\toffset: time,\n\t\t\t\t\t\tmaskPosition: value,\n\t\t\t\t\t};\n\t\t\t\t\tframes.push(frame);\n\t\t\t\t\tlastPos = curPos;\n\t\t\t\t\tlastTime = time;\n\t\t\t\t};\n\t\t\t\tpushFrame();\n\t\t\t\tlet lastTimeStamp = 0;\n\t\t\t\tthis.splittedWords.forEach((otherWord, j) => {\n\t\t\t\t\t// 停顿\n\t\t\t\t\t{\n\t\t\t\t\t\tconst curTimeStamp = otherWord.startTime - this.lyricLine.startTime;\n\t\t\t\t\t\tconst staticDuration = curTimeStamp - lastTimeStamp;\n\t\t\t\t\t\ttimeOffset += staticDuration / totalFadeDuration;\n\t\t\t\t\t\tif (staticDuration > 0) pushFrame();\n\t\t\t\t\t\tlastTimeStamp = curTimeStamp;\n\t\t\t\t\t}\n\t\t\t\t\t// 移动\n\t\t\t\t\t{\n\t\t\t\t\t\tconst fadeDuration = clampPositive(\n\t\t\t\t\t\t\totherWord.endTime - otherWord.startTime,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst rubySegments = this.getRubySegments(otherWord);\n\t\t\t\t\t\tconst rubyCharCount = rubySegments.reduce(\n\t\t\t\t\t\t\t(total, ruby) => total + ruby.word.length,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (rubyCharCount > 0) {\n\t\t\t\t\t\t\tconst widthPerChar = otherWord.width / rubyCharCount;\n\t\t\t\t\t\t\tlet charIndex = 0;\n\t\t\t\t\t\t\tfor (const ruby of rubySegments) {\n\t\t\t\t\t\t\t\tconst rubyStartTime = Number.isFinite(ruby.startTime)\n\t\t\t\t\t\t\t\t\t? ruby.startTime\n\t\t\t\t\t\t\t\t\t: otherWord.startTime;\n\t\t\t\t\t\t\t\tconst rubyEndTime = Number.isFinite(ruby.endTime)\n\t\t\t\t\t\t\t\t\t? ruby.endTime\n\t\t\t\t\t\t\t\t\t: otherWord.endTime;\n\t\t\t\t\t\t\t\tconst rubyStart = Math.max(rubyStartTime, otherWord.startTime);\n\t\t\t\t\t\t\t\tconst rubyEnd = Math.min(\n\t\t\t\t\t\t\t\t\tMath.max(rubyEndTime, rubyStart),\n\t\t\t\t\t\t\t\t\totherWord.endTime,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tconst rubyStartStamp = rubyStart - this.lyricLine.startTime;\n\t\t\t\t\t\t\t\tconst rubyStaticDuration = rubyStartStamp - lastTimeStamp;\n\t\t\t\t\t\t\t\ttimeOffset += rubyStaticDuration / totalFadeDuration;\n\t\t\t\t\t\t\t\tif (rubyStaticDuration > 0) pushFrame();\n\t\t\t\t\t\t\t\tlastTimeStamp = rubyStartStamp;\n\t\t\t\t\t\t\t\tconst rubyDuration = clampPositive(rubyEnd - rubyStart);\n\t\t\t\t\t\t\t\tconst perCharDuration = rubyDuration / ruby.word.length;\n\t\t\t\t\t\t\t\tfor (\n\t\t\t\t\t\t\t\t\tlet rubyCharIndex = 0;\n\t\t\t\t\t\t\t\t\trubyCharIndex < ruby.word.length;\n\t\t\t\t\t\t\t\t\trubyCharIndex++\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\ttimeOffset += perCharDuration / totalFadeDuration;\n\t\t\t\t\t\t\t\t\tcurPos += widthPerChar;\n\t\t\t\t\t\t\t\t\tif (j === 0 && charIndex === 0) {\n\t\t\t\t\t\t\t\t\t\tcurPos += fadeWidth * 1.5;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\tj === this.splittedWords.length - 1 &&\n\t\t\t\t\t\t\t\t\t\tcharIndex === rubyCharCount - 1\n\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\tcurPos += fadeWidth * 0.5;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (perCharDuration > 0) pushFrame();\n\t\t\t\t\t\t\t\t\tlastTimeStamp += perCharDuration;\n\t\t\t\t\t\t\t\t\tcharIndex++;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst wordEndStamp = Math.max(\n\t\t\t\t\t\t\t\totherWord.endTime - this.lyricLine.startTime,\n\t\t\t\t\t\t\t\tlastTimeStamp,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tconst wordTailDuration = wordEndStamp - lastTimeStamp;\n\t\t\t\t\t\t\ttimeOffset += wordTailDuration / totalFadeDuration;\n\t\t\t\t\t\t\tif (wordTailDuration > 0) pushFrame();\n\t\t\t\t\t\t\tlastTimeStamp = wordEndStamp;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst segmentCount = 1;\n\t\t\t\t\t\t\tconst segmentWidth = otherWord.width / segmentCount;\n\t\t\t\t\t\t\tconst segmentDuration = fadeDuration / segmentCount;\n\t\t\t\t\t\t\tfor (\n\t\t\t\t\t\t\t\tlet segmentIndex = 0;\n\t\t\t\t\t\t\t\tsegmentIndex < segmentCount;\n\t\t\t\t\t\t\t\tsegmentIndex++\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\ttimeOffset += segmentDuration / totalFadeDuration;\n\t\t\t\t\t\t\t\tcurPos += segmentWidth;\n\t\t\t\t\t\t\t\tif (j === 0 && segmentIndex === 0) {\n\t\t\t\t\t\t\t\t\tcurPos += fadeWidth * 1.5;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\tj === this.splittedWords.length - 1 &&\n\t\t\t\t\t\t\t\t\tsegmentIndex === segmentCount - 1\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\tcurPos += fadeWidth * 0.5;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (segmentDuration > 0) pushFrame();\n\t\t\t\t\t\t\t\tlastTimeStamp += segmentDuration;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\t\ta.cancel();\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\t// TODO: 如果此处动画帧计算出错,需要一个后备方案\n\t\t\t\t\t// 此处如果添加过渡函数,会导致单词时序不准确,所以不添加\n\t\t\t\t\tconst ani = wordEl.animate(frames, {\n\t\t\t\t\t\tduration: totalFadeDuration || 1,\n\t\t\t\t\t\tid: `fade-word-${word.word}-${i}`,\n\t\t\t\t\t\tfill: \"both\",\n\t\t\t\t\t});\n\t\t\t\t\tani.pause();\n\t\t\t\t\tword.maskAnimations = [ani];\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.warn(\"应用渐变动画发生错误\", frames, totalFadeDuration, err);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\tgetElement(): HTMLElement {\n\t\treturn this.element;\n\t}\n\n\tprivate updateMaskAlphaTargets(scale: number) {\n\t\tconst factor = clamp01((scale - 0.97) / 0.03);\n\t\tconst dynamicDarkAlpha = factor * 0.2 + 0.2;\n\t\tconst dynamicBrightAlpha = factor * 0.8 + 0.2;\n\n\t\tif (this.renderMode === LyricLineRenderMode.SOLID) {\n\t\t\tthis.targetBrightAlpha = dynamicDarkAlpha;\n\t\t\tthis.targetDarkAlpha = dynamicDarkAlpha;\n\t\t} else {\n\t\t\tthis.targetBrightAlpha = dynamicBrightAlpha;\n\t\t\tthis.targetDarkAlpha = dynamicDarkAlpha;\n\t\t}\n\t}\n\n\tprivate applyAlphaToDom(delta: number) {\n\t\tconst dt = delta || 0.016;\n\t\tconst ATTACK_SPEED = 50.0;\n\t\tconst RELEASE_SPEED = 7.0;\n\t\tconst getFactor = (speed: number) => 1 - Math.exp(-speed * dt);\n\n\t\t// 根据即将变亮还是变暗选择速度\n\t\t// 如果即将变亮,让速度非常快,以免播放到第一个字的时候透明度还在慢慢增加导致看不清\n\t\tconst isBrightening = this.targetBrightAlpha > this.currentBrightAlpha;\n\t\tconst brightSpeed = isBrightening ? ATTACK_SPEED : RELEASE_SPEED;\n\t\tconst brightFactor = getFactor(brightSpeed);\n\n\t\tif (Math.abs(this.targetBrightAlpha - this.currentBrightAlpha) < 0.001) {\n\t\t\tthis.currentBrightAlpha = this.targetBrightAlpha;\n\t\t} else {\n\t\t\tthis.currentBrightAlpha +=\n\t\t\t\t(this.targetBrightAlpha - this.currentBrightAlpha) * brightFactor;\n\t\t}\n\n\t\tconst isDarkening = this.targetDarkAlpha > this.currentDarkAlpha;\n\t\tconst darkSpeed = isDarkening ? ATTACK_SPEED : RELEASE_SPEED;\n\t\tconst darkFactor = getFactor(darkSpeed);\n\n\t\tif (Math.abs(this.targetDarkAlpha - this.currentDarkAlpha) < 0.001) {\n\t\t\tthis.currentDarkAlpha = this.targetDarkAlpha;\n\t\t} else {\n\t\t\tthis.currentDarkAlpha +=\n\t\t\t\t(this.targetDarkAlpha - this.currentDarkAlpha) * darkFactor;\n\t\t}\n\n\t\tthis.element.style.setProperty(\n\t\t\t\"--bright-mask-alpha\",\n\t\t\tthis.currentBrightAlpha.toFixed(3),\n\t\t);\n\t\tthis.element.style.setProperty(\n\t\t\t\"--dark-mask-alpha\",\n\t\t\tthis.currentDarkAlpha.toFixed(3),\n\t\t);\n\t}\n\n\toverride setTransform(\n\t\tscale: number = this.scale,\n\t\topacity = 1,\n\t\tblur = 0,\n\t\tforce = false,\n\t\tdelay = 0,\n\t\tmode: LyricLineRenderMode = LyricLineRenderMode.SOLID,\n\t): void {\n\t\tsuper.setTransform(scale, opacity, blur, force, delay);\n\n\t\tthis.renderMode = mode;\n\t\tconst enableSpring = this.lyricPlayer.getEnableSpring();\n\n\t\tthis.top = 0;\n\t\tthis.scale = scale;\n\t\tthis.delay = (delay * 1000) | 0;\n\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\t\tmain.style.opacity = `${opacity}`;\n\n\t\tif (force || !enableSpring) {\n\t\t\tthis.blur = Math.min(32, blur);\n\t\t\tthis.lineTransforms.scale.setPosition(scale);\n\n\t\t\tthis.rebuildStyle();\n\n\t\t\tconst currentScale = this.lineTransforms.scale.getCurrentPosition();\n\t\t\tthis.updateMaskAlphaTargets(currentScale / 100);\n\t\t\tthis.currentBrightAlpha = this.targetBrightAlpha;\n\t\t\tthis.currentDarkAlpha = this.targetDarkAlpha;\n\t\t\tthis.element.style.setProperty(\n\t\t\t\t\"--bright-mask-alpha\",\n\t\t\t\tString(this.currentBrightAlpha),\n\t\t\t);\n\t\t\tthis.element.style.setProperty(\n\t\t\t\t\"--dark-mask-alpha\",\n\t\t\t\tString(this.currentDarkAlpha),\n\t\t\t);\n\t\t} else {\n\t\t\tthis.lineTransforms.scale.setTargetPosition(scale);\n\t\t\tif (this.blur !== Math.min(5, blur)) {\n\t\t\t\tthis.blur = Math.min(5, blur);\n\t\t\t\tthis.element.style.filter = `blur(${blur.toFixed(3)}px)`;\n\t\t\t}\n\t\t}\n\t}\n\n\tupdate(delta = 0): void {\n\t\tif (!this.lyricPlayer.getEnableSpring()) return;\n\n\t\tthis.lineTransforms.scale.update(delta);\n\t\tthis.rebuildStyle();\n\n\t\tif (!this.built) return;\n\n\t\tconst currentScale = this.lineTransforms.scale.getCurrentPosition() / 100;\n\t\tthis.updateMaskAlphaTargets(currentScale);\n\t\tthis.applyAlphaToDom(delta);\n\t}\n\n\t_getDebugTargetPos(): string {\n\t\treturn `[位移: ${this.top}; 缩放: ${this.scale}; 延时: ${this.delay}]`;\n\t}\n\n\tteardownContent(): void {\n\t\tif (this.built) {\n\t\t\tthis.disposeElements();\n\t\t\tthis.built = false;\n\t\t}\n\t}\n\n\tprivate disposeElements() {\n\t\tthis.balancer?.reset();\n\t\tfor (const realWord of this.splittedWords) {\n\t\t\tfor (const a of realWord.elementAnimations) {\n\t\t\t\ta.cancel();\n\t\t\t}\n\t\t\tfor (const a of realWord.maskAnimations) {\n\t\t\t\ta.cancel();\n\t\t\t}\n\t\t\tfor (const sub of realWord.subElements) {\n\t\t\t\tsub.remove();\n\t\t\t\tsub.parentNode?.removeChild(sub);\n\t\t\t}\n\t\t\trealWord.elementAnimations = [];\n\t\t\trealWord.maskAnimations = [];\n\t\t\trealWord.subElements = [];\n\t\t\tif (realWord.mainElement?.parentNode) {\n\t\t\t\trealWord.mainElement.parentNode.removeChild(realWord.mainElement);\n\t\t\t}\n\t\t}\n\t\tthis.splittedWords = [];\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\t\tconst trans = this.element.children[1] as HTMLDivElement;\n\t\tconst roman = this.element.children[2] as HTMLDivElement;\n\t\tif (main) main.innerHTML = \"\";\n\t\tif (trans) trans.innerHTML = \"\";\n\t\tif (roman) roman.innerHTML = \"\";\n\t}\n\toverride dispose(): void {\n\t\tthis.disposeElements();\n\t\tthis.lyricPlayer.resizeObserver.unobserve(this.element);\n\t\tthis.element.remove();\n\t}\n}\n","/**\n * @fileoverview\n * 一个播放歌词的组件\n * @author SteveXMH\n */\n\nimport type { LyricLine } from \"#interfaces\";\nimport \"#styles/index.css\";\nimport { LyricPlayerBase } from \"#lyric/base/index.ts\";\nimport type { LyricLineBase } from \"#lyric/base/line.ts\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { LyricLineGroup } from \"./lyric-group.ts\";\nimport { LyricLineEl, type RawLyricLineMouseEvent } from \"./lyric-line.ts\";\n\n/**\n * 歌词行鼠标相关事件,可以获取到歌词行的索引和歌词行元素\n */\nexport class LyricLineMouseEvent extends MouseEvent {\n\tconstructor(\n\t\t/**\n\t\t * 歌词行索引\n\t\t */\n\t\tpublic readonly lineIndex: number,\n\t\t/**\n\t\t * 歌词行元素\n\t\t */\n\t\tpublic readonly line: LyricLineBase,\n\t\tevent: MouseEvent,\n\t) {\n\t\tsuper(`line-${event.type}`, event);\n\t}\n}\n\nexport type LyricLineMouseEventListener = (evt: LyricLineMouseEvent) => void;\n\n/**\n * 歌词播放组件,本框架的核心组件\n *\n * 尽可能贴切 Apple Music for iPad 的歌词效果设计,且做了力所能及的优化措施\n */\nexport class DomLyricPlayer extends LyricPlayerBase {\n\toverride currentLyricGroups: LyricLineGroup[] = [];\n\n\toverride onResize(): void {\n\t\tconst computedStyles = getComputedStyle(this.element);\n\t\tthis._baseFontSize = Number.parseFloat(computedStyles.fontSize);\n\t\tthis.rebuildStyle();\n\t}\n\n\treadonly supportPlusLighter: boolean = CSS.supports(\n\t\t\"mix-blend-mode\",\n\t\t\"plus-lighter\",\n\t);\n\treadonly supportMaskImage: boolean = CSS.supports(\"mask-image\", \"none\");\n\treadonly innerSize: [number, number] = [0, 0];\n\tprivate readonly onLineClickedHandler = (e: RawLyricLineMouseEvent) => {\n\t\tconst evt = new LyricLineMouseEvent(\n\t\t\tthis.lyricLinesIndexes.get(e.line) ?? -1,\n\t\t\te.line,\n\t\t\te,\n\t\t);\n\t\tif (!this.dispatchEvent(evt)) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\t};\n\t/**\n\t * 是否为非逐词歌词\n\t * @internal\n\t */\n\t_getIsNonDynamic(): boolean {\n\t\treturn this.isNonDynamic;\n\t}\n\tprivate _baseFontSize = Number.parseFloat(\n\t\tgetComputedStyle(this.element).fontSize,\n\t);\n\tpublic get baseFontSize(): number {\n\t\treturn this._baseFontSize;\n\t}\n\tconstructor() {\n\t\tsuper();\n\t\tthis.onResize();\n\t\tthis.element.classList.add(\"amll-lyric-player\", \"dom\");\n\t\tif (this.disableSpring) {\n\t\t\tthis.element.classList.add(styles.disableSpring);\n\t\t}\n\t}\n\n\tprivate rebuildStyle() {\n\t\t// const width = this.innerSize[0];\n\t\t// const height = this.innerSize[1];\n\t\t// this.element.style.setProperty(\"--amll-lp-width\", `${width.toFixed(4)}px`);\n\t\t// this.element.style.setProperty(\n\t\t// \t\"--amll-lp-height\",\n\t\t// \t`${height.toFixed(4)}px`,\n\t\t// );\n\t}\n\n\toverride setWordFadeWidth(value = 0.5): void {\n\t\tsuper.setWordFadeWidth(value);\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.mainLine.updateMaskImageSync();\n\t\t\tgroup.bgLine?.updateMaskImageSync();\n\t\t}\n\t}\n\n\t/**\n\t * 设置当前播放歌词,要注意传入后这个数组内的信息不得修改,否则会发生错误\n\t * @param lines 歌词数组\n\t * @param initialTime 初始时间,默认为 0\n\t */\n\toverride setLyricLines(lines: LyricLine[], initialTime = 0): void {\n\t\tsuper.setLyricLines(lines, initialTime);\n\t\tif (this.hasDuetLine) {\n\t\t\tthis.element.classList.add(styles.hasDuetLine);\n\t\t} else {\n\t\t\tthis.element.classList.remove(styles.hasDuetLine);\n\t\t}\n\t\tif (!this.supportMaskImage) {\n\t\t\tthis.element.style.setProperty(\"--amll-player-time\", `${initialTime}`);\n\t\t}\n\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tconst linesToDispose = [group.mainLine, group.bgLine].filter(\n\t\t\t\t(line) => !!line,\n\t\t\t);\n\n\t\t\tfor (const line of linesToDispose) {\n\t\t\t\tline.removeMouseEventListener(\"click\", this.onLineClickedHandler);\n\t\t\t\tline.removeMouseEventListener(\"contextmenu\", this.onLineClickedHandler);\n\t\t\t}\n\t\t\tgroup.dispose();\n\t\t}\n\t\tthis.currentLyricGroups = [];\n\n\t\tlet currentGroup: LyricLineGroup | null = null;\n\n\t\tfor (let i = 0; i < this.processedLines.length; i++) {\n\t\t\tconst line = this.processedLines[i];\n\t\t\tconst lineEl = new LyricLineEl(this, line);\n\n\t\t\tlineEl.addMouseEventListener(\"click\", this.onLineClickedHandler);\n\t\t\tlineEl.addMouseEventListener(\"contextmenu\", this.onLineClickedHandler);\n\n\t\t\tthis.lyricLinesIndexes.set(lineEl, i);\n\n\t\t\tif (!line.isBG || !currentGroup) {\n\t\t\t\tcurrentGroup = new LyricLineGroup(this, lineEl);\n\t\t\t\tthis.currentLyricGroups.push(currentGroup);\n\t\t\t\tthis.lyricGroupElementMap.set(currentGroup.element, currentGroup);\n\t\t\t} else {\n\t\t\t\tcurrentGroup.addBgLine(lineEl);\n\t\t\t}\n\t\t}\n\n\t\tthis.setLinePosXSpringParams({});\n\t\tthis.setLinePosYSpringParams({});\n\t\tthis.setLineScaleSpringParams({});\n\t\tthis.setCurrentTime(initialTime, true);\n\t\tthis.calcLayout(true);\n\t\tthis.update(0);\n\t}\n\n\toverride pause(): void {\n\t\tsuper.pause();\n\t\tthis.element.classList.remove(styles.playing);\n\t\tthis.interludeDots.pause();\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.mainLine.pause();\n\t\t\tgroup.bgLine?.pause();\n\t\t}\n\t}\n\n\toverride resume(): void {\n\t\tsuper.resume();\n\t\tthis.element.classList.add(styles.playing);\n\t\tthis.interludeDots.resume();\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.mainLine.resume();\n\t\t\tgroup.bgLine?.resume();\n\t\t}\n\t}\n\n\toverride update(delta = 0): void {\n\t\tif (!this.timelineState.initialLayoutFinished) return;\n\t\tsuper.update(delta);\n\t\tif (!this.supportMaskImage) {\n\t\t\tthis.element.style.setProperty(\n\t\t\t\t\"--amll-player-time\",\n\t\t\t\t`${this.timelineState.currentTime}`,\n\t\t\t);\n\t\t}\n\t\tif (!this.isPageVisible) return;\n\t\tconst deltaS = delta / 1000;\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.update(deltaS);\n\t\t}\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tthis.element.remove();\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.dispose();\n\t\t}\n\t\tthis.bottomLine.dispose();\n\t\tthis.interludeDots.dispose();\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"amll-core.mjs","names":["meshVertShader","meshFragShader","styles","styles","styles","styles","styles","styles"],"sources":["../src/bg-render/base.ts","../src/utils/resource.ts","../src/bg-render/img.ts","../src/utils/clamp.ts","../src/bg-render/mesh-renderer/cp-presets.ts","../src/bg-render/mesh-renderer/cp-generate.ts","../src/bg-render/mesh-renderer/index.ts","../src/bg-render/pixi-renderer.ts","../src/bg-render/index.ts","../src/styles/lyric-player.module.css","../src/utils/optimize-lyric.ts","../src/lyric-player/dom/interlude-dots.ts","../src/utils/schedule.ts","../src/utils/derivative.ts","../src/utils/spring.ts","../src/lyric-player/base/bottom-line.ts","../src/lyric-player/base/consts.ts","../src/lyric-player/base/layout.ts","../src/lyric-player/base/scroll.ts","../src/utils/eq-set.ts","../src/lyric-player/base/timeline.ts","../src/lyric-player/base/index.ts","../src/lyric-player/base/group.ts","../src/lyric-player/dom/lyric-group.ts","../src/utils/is-cjk.ts","../src/lyric-player/base/line.ts","../src/utils/lyric-line-break.ts","../src/utils/line-balancer.ts","../src/utils/lyric-split-words.ts","../src/utils/matrix.ts","../src/lyric-player/dom/lyric-line.ts","../src/lyric-player/dom/index.ts"],"sourcesContent":["import type { Disposable, HasElement } from \"../interfaces.ts\";\n\nexport abstract class AbstractBaseRenderer implements Disposable, HasElement {\n\t/**\n\t * 修改背景的流动速度,数字越大越快,默认为 8\n\t * @param speed 背景的流动速度,默认为 8\n\t */\n\tabstract setFlowSpeed(speed: number): void;\n\t/**\n\t * 修改背景的渲染比例,默认是 0.5\n\t *\n\t * 一般情况下这个程度既没有明显瑕疵也不会特别吃性能\n\t * @param scale 背景的渲染比例\n\t */\n\tabstract setRenderScale(scale: number): void;\n\t/**\n\t * 是否启用静态模式,即图片在更换后就会保持静止状态并禁用更新,以节省性能\n\t * @param enable 是否启用静态模式\n\t */\n\tabstract setStaticMode(enable: boolean): void;\n\t/**\n\t * 修改背景动画帧率,默认是 30 FPS\n\t *\n\t * 如果设置成 0 则会停止动画\n\t * @param fps 目标帧率,默认 30 FPS\n\t */\n\tabstract setFPS(fps: number): void;\n\t/**\n\t * 暂停背景动画,画面即便是更新了图片也不会发生变化\n\t */\n\tabstract pause(): void;\n\t/**\n\t * 恢复播放背景动画\n\t */\n\tabstract resume(): void;\n\t/**\n\t * 设置背景专辑资源,纹理加载并设置完成后会返回\n\t * @param albumSource 专辑的资源链接,可以是图片或视频链接,抑或是任意 img/video 元素,如果提供字符串链接且为视频则需要指定第二个参数\n\t */\n\tabstract setAlbum(\n\t\talbumSource: string | HTMLImageElement | HTMLVideoElement,\n\t\tisVideo?: boolean,\n\t): Promise<void>;\n\t/**\n\t * 设置低频的音量大小,范围在 80hz-120hz 之间为宜,取值范围在 [0.0-1.0] 之间\n\t *\n\t * 部分渲染器会根据音量大小调整背景效果(例如根据鼓点跳动)\n\t *\n\t * 如果无法获取到类似的数据,请传入 1.0 作为默认值,或不做任何处理(默认值即 1.0)\n\t * @param volume 低频的音量大小,范围在 50hz-120hz 之间为宜,取值范围在 [0.0-1.0] 之间\n\t */\n\tabstract setLowFreqVolume(volume: number): void;\n\t/**\n\t * 设置背景是否根据“是否有歌词”这个特征调整自身效果,例如有歌词时会变得更加活跃\n\t *\n\t * 部分渲染器会根据这个特征调整自身效果\n\t *\n\t * 如果不确定是否需要赋值或无法知晓是否包含歌词,请传入 true 或不做任何处理(默认值为 true)\n\t *\n\t * @param hasLyric 是否有歌词,如不确定是否需要赋值,请传入 true 或不做任何处理(默认值为 true)\n\t */\n\tabstract setHasLyric(hasLyric: boolean): void;\n\tabstract dispose(): void;\n\tabstract getElement(): HTMLElement;\n}\n\nfunction clamp1(x: number): number {\n\treturn Math.max(1, x);\n}\n\nexport abstract class BaseRenderer extends AbstractBaseRenderer {\n\tprivate observer: ResizeObserver;\n\tprotected flowSpeed = 1;\n\tprotected currerntRenderScale = 0.75;\n\tconstructor(protected canvas: HTMLCanvasElement) {\n\t\tsuper();\n\t\tthis.observer = new ResizeObserver(() => {\n\t\t\tconst width = clamp1(\n\t\t\t\tcanvas.clientWidth * window.devicePixelRatio * this.currerntRenderScale,\n\t\t\t);\n\t\t\tconst height = clamp1(\n\t\t\t\tcanvas.clientHeight *\n\t\t\t\t\twindow.devicePixelRatio *\n\t\t\t\t\tthis.currerntRenderScale,\n\t\t\t);\n\t\t\tthis.onResize(width, height);\n\t\t});\n\t\tthis.observer.observe(canvas);\n\t}\n\tsetRenderScale(scale: number): void {\n\t\tthis.currerntRenderScale = scale;\n\t\tthis.onResize(\n\t\t\tthis.canvas.clientWidth *\n\t\t\t\twindow.devicePixelRatio *\n\t\t\t\tthis.currerntRenderScale,\n\t\t\tthis.canvas.clientHeight *\n\t\t\t\twindow.devicePixelRatio *\n\t\t\t\tthis.currerntRenderScale,\n\t\t);\n\t}\n\t/**\n\t * 当画板元素大小发生变化时此函数会被调用\n\t * 可以在此处重设和渲染器相关的尺寸设置\n\t * 考虑到初始化的时候元素不一定在文档中或出于某些特殊样式状态,尺寸长宽有可能会为 0,请注意进行特判处理\n\t * @param width 画板元素实际的物理像素宽度,有可能为 0\n\t * @param height 画板元素实际的物理像素高度,有可能为 0\n\t */\n\tprotected onResize(width: number, height: number): void {\n\t\tthis.canvas.width = width;\n\t\tthis.canvas.height = height;\n\t}\n\t/**\n\t * 修改背景的流动速度,数字越大越快,默认为 1\n\t * @param speed 背景的流动速度,默认为 1\n\t */\n\tsetFlowSpeed(speed: number): void {\n\t\tthis.flowSpeed = speed;\n\t}\n\t/**\n\t * 是否启用静态模式,即图片在更换后就会保持静止状态并禁用更新,以节省性能\n\t * @param enable 是否启用静态模式\n\t */\n\tabstract override setStaticMode(enable: boolean): void;\n\t/**\n\t * 修改背景动画帧率,默认是 30 FPS\n\t *\n\t * 如果设置成 0 则会停止动画\n\t * @param fps 目标帧率,默认 30 FPS\n\t */\n\tabstract override setFPS(fps: number): void;\n\t/**\n\t * 暂停背景动画,画面即便是更新了图片也不会发生变化\n\t */\n\tabstract override pause(): void;\n\t/**\n\t * 恢复播放背景动画\n\t */\n\tabstract override resume(): void;\n\t/**\n\t * 设置背景专辑资源,纹理加载并设置完成后会返回\n\t * @param albumSource 专辑的资源链接,可以是图片或视频链接,抑或是任意 img/video 元素,如果提供字符串链接且为视频则需要指定第二个参数\n\t */\n\tabstract override setAlbum(\n\t\talbumSource: string | HTMLImageElement | HTMLVideoElement,\n\t\tisVideo?: boolean,\n\t): Promise<void>;\n\tdispose(): void {\n\t\tthis.observer.disconnect();\n\t\tthis.canvas.remove();\n\t}\n\toverride getElement(): HTMLElement {\n\t\treturn this.canvas;\n\t}\n}\n","export function loadImage(imageUrl: string): Promise<HTMLImageElement> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst img = document.createElement(\"img\");\n\t\timg.onload = () => resolve(img);\n\t\timg.onerror = reject;\n\t\timg.src = imageUrl;\n\t\timg.crossOrigin = \"anonymous\";\n\t\timg.loading = \"eager\";\n\t});\n}\n\nexport function loadVideo(videoUrl: string): Promise<HTMLVideoElement> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst video = document.createElement(\"video\");\n\t\tlet playing = false;\n\t\tlet timeupdate = false;\n\t\tlet rejected = false;\n\t\tvideo.addEventListener(\n\t\t\t\"playing\",\n\t\t\t() => {\n\t\t\t\tplaying = true;\n\t\t\t\tcheckReady();\n\t\t\t},\n\t\t\ttrue,\n\t\t);\n\t\tvideo.addEventListener(\n\t\t\t\"timeupdate\",\n\t\t\t() => {\n\t\t\t\ttimeupdate = true;\n\t\t\t\tcheckReady();\n\t\t\t},\n\t\t\ttrue,\n\t\t);\n\t\tvideo.addEventListener(\n\t\t\t\"error\",\n\t\t\t(err) => {\n\t\t\t\trejected = true;\n\t\t\t\treject(err);\n\t\t\t},\n\t\t\ttrue,\n\t\t);\n\t\tfunction checkReady() {\n\t\t\tif (playing && timeupdate && !rejected) {\n\t\t\t\tresolve(video);\n\t\t\t}\n\t\t}\n\t\tvideo.src = videoUrl;\n\t\tvideo.playsInline = true;\n\t\tvideo.crossOrigin = \"anonymous\";\n\t\tvideo.autoplay = true;\n\t\tvideo.loop = true;\n\t\tvideo.muted = true;\n\t\tvideo.play();\n\t});\n}\n\nexport function loadResourceFromUrl(\n\turl: string,\n\tisVideo = false,\n): Promise<HTMLImageElement | HTMLVideoElement> {\n\treturn isVideo ? loadVideo(url) : loadImage(url);\n}\n\nexport function loadResourceFromElement(\n\telement: HTMLImageElement | HTMLVideoElement,\n): Promise<HTMLImageElement | HTMLVideoElement> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (\n\t\t\telement instanceof HTMLImageElement\n\t\t\t\t? element.complete\n\t\t\t\t: element.readyState >= 3\n\t\t) {\n\t\t\tresolve(element);\n\t\t} else {\n\t\t\telement.onload = () => resolve(element);\n\t\t\telement.onerror = reject;\n\t\t}\n\t});\n}\n","export function blurImage(\n\timageData: ImageData,\n\tradius: number,\n\tquality: number,\n): void {\n\tconst pixels = imageData.data;\n\tconst width = imageData.width;\n\tconst height = imageData.height;\n\n\tlet rsum: number;\n\tlet gsum: number;\n\tlet bsum: number;\n\tlet asum: number;\n\tlet x: number;\n\tlet y: number;\n\tlet i: number;\n\tlet p: number;\n\tlet p1: number;\n\tlet p2: number;\n\tlet yp: number;\n\tlet yi: number;\n\tlet yw: number;\n\tconst wm = width - 1;\n\tconst hm = height - 1;\n\tconst rad1x = radius + 1;\n\tconst divx = radius + rad1x;\n\tconst rad1y = radius + 1;\n\tconst divy = radius + rad1y;\n\tconst div2 = 1 / (divx * divy);\n\n\tconst r: number[] = [];\n\tconst g: number[] = [];\n\tconst b: number[] = [];\n\tconst a: number[] = [];\n\n\tconst vmin: number[] = [];\n\tconst vmax: number[] = [];\n\n\twhile (quality-- > 0) {\n\t\tyw = yi = 0;\n\n\t\tfor (y = 0; y < height; y++) {\n\t\t\trsum = pixels[yw] * rad1x;\n\t\t\tgsum = pixels[yw + 1] * rad1x;\n\t\t\tbsum = pixels[yw + 2] * rad1x;\n\t\t\tasum = pixels[yw + 3] * rad1x;\n\n\t\t\tfor (i = 1; i <= radius; i++) {\n\t\t\t\tp = yw + ((i > wm ? wm : i) << 2);\n\t\t\t\trsum += pixels[p++];\n\t\t\t\tgsum += pixels[p++];\n\t\t\t\tbsum += pixels[p++];\n\t\t\t\tasum += pixels[p];\n\t\t\t}\n\n\t\t\tfor (x = 0; x < width; x++) {\n\t\t\t\tr[yi] = rsum;\n\t\t\t\tg[yi] = gsum;\n\t\t\t\tb[yi] = bsum;\n\t\t\t\ta[yi] = asum;\n\n\t\t\t\tif (y === 0) {\n\t\t\t\t\tvmin[x] = Math.min(x + rad1x, wm) << 2;\n\t\t\t\t\tvmax[x] = Math.max(x - radius, 0) << 2;\n\t\t\t\t}\n\n\t\t\t\tp1 = yw + vmin[x];\n\t\t\t\tp2 = yw + vmax[x];\n\n\t\t\t\trsum += pixels[p1++] - pixels[p2++];\n\t\t\t\tgsum += pixels[p1++] - pixels[p2++];\n\t\t\t\tbsum += pixels[p1++] - pixels[p2++];\n\t\t\t\tasum += pixels[p1] - pixels[p2];\n\n\t\t\t\tyi++;\n\t\t\t}\n\t\t\tyw += width << 2;\n\t\t}\n\n\t\tfor (x = 0; x < width; x++) {\n\t\t\typ = x;\n\t\t\trsum = r[yp] * rad1y;\n\t\t\tgsum = g[yp] * rad1y;\n\t\t\tbsum = b[yp] * rad1y;\n\t\t\tasum = a[yp] * rad1y;\n\n\t\t\tfor (i = 1; i <= radius; i++) {\n\t\t\t\typ += i > hm ? 0 : width;\n\t\t\t\trsum += r[yp];\n\t\t\t\tgsum += g[yp];\n\t\t\t\tbsum += b[yp];\n\t\t\t\tasum += a[yp];\n\t\t\t}\n\n\t\t\tyi = x << 2;\n\t\t\tfor (y = 0; y < height; y++) {\n\t\t\t\tpixels[yi] = (rsum * div2 + 0.5) | 0;\n\t\t\t\tpixels[yi + 1] = (gsum * div2 + 0.5) | 0;\n\t\t\t\tpixels[yi + 2] = (bsum * div2 + 0.5) | 0;\n\t\t\t\tpixels[yi + 3] = (asum * div2 + 0.5) | 0;\n\n\t\t\t\tif (x === 0) {\n\t\t\t\t\tvmin[y] = Math.min(y + rad1y, hm) * width;\n\t\t\t\t\tvmax[y] = Math.max(y - radius, 0) * width;\n\t\t\t\t}\n\n\t\t\t\tp1 = x + vmin[y];\n\t\t\t\tp2 = x + vmax[y];\n\n\t\t\t\trsum += r[p1] - r[p2];\n\t\t\t\tgsum += g[p1] - g[p2];\n\t\t\t\tbsum += b[p1] - b[p2];\n\t\t\t\tasum += a[p1] - a[p2];\n\n\t\t\t\tyi += width << 2;\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport function saturateImage(imageData: ImageData, saturation: number): void {\n\tconst pixels = imageData.data;\n\n\tfor (let i = 0; i < pixels.length; i += 4) {\n\t\tconst r = pixels[i];\n\t\tconst g = pixels[i + 1];\n\t\tconst b = pixels[i + 2];\n\t\tconst a = pixels[i + 3];\n\t\tconst gray = r * 0.3 + g * 0.59 + b * 0.11;\n\t\tpixels[i] = gray * (1 - saturation) + r * saturation;\n\t\tpixels[i + 1] = gray * (1 - saturation) + g * saturation;\n\t\tpixels[i + 2] = gray * (1 - saturation) + b * saturation;\n\t\tpixels[i + 3] = a;\n\t}\n}\n\nexport function brightnessImage(\n\timageData: ImageData,\n\tbrightness: number,\n): void {\n\tconst pixels = imageData.data;\n\n\tfor (let i = 0; i < pixels.length; i += 4) {\n\t\tconst r = pixels[i];\n\t\tconst g = pixels[i + 1];\n\t\tconst b = pixels[i + 2];\n\t\tconst a = pixels[i + 3];\n\t\tpixels[i] = r * brightness;\n\t\tpixels[i + 1] = g * brightness;\n\t\tpixels[i + 2] = b * brightness;\n\t\tpixels[i + 3] = a;\n\t}\n}\n\nexport function contrastImage(imageData: ImageData, contrast: number): void {\n\tconst pixels = imageData.data;\n\n\tfor (let i = 0; i < pixels.length; i += 4) {\n\t\tconst r = pixels[i];\n\t\tconst g = pixels[i + 1];\n\t\tconst b = pixels[i + 2];\n\t\tconst a = pixels[i + 3];\n\t\tpixels[i] = (r - 128) * contrast + 128;\n\t\tpixels[i + 1] = (g - 128) * contrast + 128;\n\t\tpixels[i + 2] = (b - 128) * contrast + 128;\n\t\tpixels[i + 3] = a;\n\t}\n}\n","export function clamp(x: number, min: number, max: number): number {\n\treturn Math.min(Math.max(x, min), max);\n}\n\nexport function clamp01(x: number): number {\n\treturn clamp(x, 0, 1);\n}\n\nexport function clampPositive(x: number): number {\n\treturn Math.max(0, x);\n}\n","/** @internal */\nexport interface ControlPointConf {\n\tcx: number;\n\tcy: number;\n\tx: number;\n\ty: number;\n\tur: number;\n\tvr: number;\n\tup: number;\n\tvp: number;\n}\n\n/** @internal */\nexport interface ControlPointPreset {\n\twidth: number;\n\theight: number;\n\tconf: ControlPointConf[];\n}\n\n/** @internal */\nexport const p = (\n\tcx: number,\n\tcy: number,\n\tx: number,\n\ty: number,\n\tur = 0,\n\tvr = 0,\n\tup = 1,\n\tvp = 1,\n) => Object.freeze({ cx, cy, x, y, ur, vr, up, vp }) as ControlPointConf;\n/** @internal */\nexport const preset = (\n\twidth: number,\n\theight: number,\n\tconf: ControlPointConf[],\n) => Object.freeze({ width, height, conf }) as ControlPointPreset;\n\nexport const CONTROL_POINT_PRESETS: ControlPointPreset[] = [\n\t// TODO: 竖屏推荐\n\tpreset(5, 5, [\n\t\tp(0, 0, -1, -1, 0, 0, 1, 1),\n\t\tp(1, 0, -0.5, -1, 0, 0, 1, 1),\n\t\tp(2, 0, 0, -1, 0, 0, 1, 1),\n\t\tp(3, 0, 0.5, -1, 0, 0, 1, 1),\n\t\tp(4, 0, 1, -1, 0, 0, 1, 1),\n\t\tp(0, 1, -1, -0.5, 0, 0, 1, 1),\n\t\tp(1, 1, -0.5, -0.5, 0, 0, 1, 1),\n\t\tp(2, 1, -0.0052029684413368305, -0.6131420587090777, 0, 0, 1, 1),\n\t\tp(3, 1, 0.5884227308309977, -0.3990805107556692, 0, 0, 1, 1),\n\t\tp(4, 1, 1, -0.5, 0, 0, 1, 1),\n\t\tp(0, 2, -1, 0, 0, 0, 1, 1),\n\t\tp(1, 2, -0.4210024670505933, -0.11895058380429502, 0, 0, 1, 1),\n\t\tp(2, 2, -0.1019613423315412, -0.023812118047224606, 0, -47, 0.629, 0.849),\n\t\tp(3, 2, 0.40275125660925437, -0.06345314544600389, 0, 0, 1, 1),\n\t\tp(4, 2, 1, 0, 0, 0, 1, 1),\n\t\tp(0, 3, -1, 0.5, 0, 0, 1, 1),\n\t\tp(1, 3, 0.06801958477287173, 0.5205913248960121, -31, -45, 1, 1),\n\t\tp(2, 3, 0.21446469120128908, 0.29331610114301043, 6, -56, 0.566, 1.321),\n\t\tp(3, 3, 0.5, 0.5, 0, 0, 1, 1),\n\t\tp(4, 3, 1, 0.5, 0, 0, 1, 1),\n\t\tp(0, 4, -1, 1, 0, 0, 1, 1),\n\t\tp(1, 4, -0.31378372841550195, 1, 0, 0, 1, 1),\n\t\tp(2, 4, 0.26153633255328046, 1, 0, 0, 1, 1),\n\t\tp(3, 4, 0.5, 1, 0, 0, 1, 1),\n\t\tp(4, 4, 1, 1, 0, 0, 1, 1),\n\t]),\n\t// TODO: 横屏推荐\n\tpreset(4, 4, [\n\t\tp(0, 0, -1, -1, 0, 0, 1, 1),\n\t\tp(1, 0, -0.33333333333333337, -1, 0, 0, 1, 1),\n\t\tp(2, 0, 0.33333333333333326, -1, 0, 0, 1, 1),\n\t\tp(3, 0, 1, -1, 0, 0, 1, 1),\n\t\tp(0, 1, -1, -0.04495399932657351, 0, 0, 1, 1),\n\t\tp(1, 1, -0.24056117520129328, -0.22465999020104, 0, 0, 1, 1),\n\t\tp(2, 1, 0.334758885767489, -0.00531297192779423, 0, 0, 1, 1),\n\t\tp(3, 1, 0.9989920470678106, -0.3382976020775408, 8, 0, 0.566, 1.792),\n\t\tp(0, 2, -1, 0.33333333333333326, 0, 0, 1, 1),\n\t\tp(1, 2, -0.3425497314639411, -0.000027501607956947893, 0, 0, 1, 1),\n\t\tp(2, 2, 0.3321437945812673, 0.1981776353859399, 0, 0, 1, 1),\n\t\tp(3, 2, 1, 0.0766118180296832, 0, 0, 1, 1),\n\t\tp(0, 3, -1, 1, 0, 0, 1, 1),\n\t\tp(1, 3, -0.33333333333333337, 1, 0, 0, 1, 1),\n\t\tp(2, 3, 0.33333333333333326, 1, 0, 0, 1, 1),\n\t\tp(3, 3, 1, 1, 0, 0, 1, 1),\n\t]),\n\tpreset(4, 4, [\n\t\tp(0, 0, -1, -1, 0, 0, 1, 2.075),\n\t\tp(1, 0, -0.33333333333333337, -1, 0, 0, 1, 1),\n\t\tp(2, 0, 0.33333333333333326, -1, 0, 0, 1, 1),\n\t\tp(3, 0, 1, -1, 0, 0, 1, 1),\n\t\tp(0, 1, -1, -0.4545779491139603, 0, 0, 1, 1),\n\t\tp(1, 1, -0.33333333333333337, -0.33333333333333337, 0, 0, 1, 1),\n\t\tp(2, 1, 0.0889403142626457, -0.6025711180694033, -32, 45, 1, 1),\n\t\tp(3, 1, 1, -0.33333333333333337, 0, 0, 1, 1),\n\t\tp(0, 2, -1, -0.07402408608567845, 1, 0, 1, 0.094),\n\t\tp(1, 2, -0.2719422694359541, 0.09775369930903222, 25, -18, 1.321, 0),\n\t\tp(2, 2, 0.19877414408395877, 0.4307383294587789, 48, -40, 0.755, 0.975),\n\t\tp(3, 2, 1, 0.33333333333333326, -37, 0, 1, 1),\n\t\tp(0, 3, -1, 1, 0, 0, 1, 1),\n\t\tp(1, 3, -0.33333333333333337, 1, 0, 0, 1, 1),\n\t\tp(2, 3, 0.5125850864305672, 1, -20, -18, 0, 1.604),\n\t\tp(3, 3, 1, 1, 0, 0, 1, 1),\n\t]),\n\tpreset(5, 5, [\n\t\tp(0, 0, -1, -1, 0, 0, 1, 1),\n\t\tp(1, 0, -0.4501953125, -1, 0, 55, 1, 2.075),\n\t\tp(2, 0, 0.1953125, -1, 0, 0, 1, 1),\n\t\tp(3, 0, 0.4580078125, -1, 0, -25, 1, 1),\n\t\tp(4, 0, 1, -1, 0, 0, 1, 1),\n\t\tp(0, 1, -1, -0.2514475377525607, -16, 0, 2.327, 0.943),\n\t\tp(1, 1, -0.55859375, -0.6609325945787148, 47, 0, 2.358, 0.377),\n\t\tp(2, 1, 0.232421875, -0.5244375756366635, -66, -25, 1.855, 1.164),\n\t\tp(3, 1, 0.685546875, -0.3753706470552125, 0, 0, 1, 1),\n\t\tp(4, 1, 1, -0.6699125300354287, 0, 0, 1, 1),\n\t\tp(0, 2, -1, 0.035910396862284255, 0, 0, 1, 1),\n\t\tp(1, 2, -0.4921875, 0.005378616309457018, 90, 23, 1, 1.981),\n\t\tp(2, 2, 0.021484375, -0.1365043639066228, 0, 42, 1, 1),\n\t\tp(3, 2, 0.4765625, 0.05925822904974043, -30, 0, 1.95, 0.44),\n\t\tp(4, 2, 1, 0.251428847823418, 0, 0, 1, 1),\n\t\tp(0, 3, -1, 0.6968336464764276, -68, 0, 1, 0.786),\n\t\tp(1, 3, -0.6904296875, 0.5890744209958608, -68, 0, 1, 1),\n\t\tp(2, 3, 0.1845703125, 0.3879238667654693, 61, 0, 1, 1),\n\t\tp(3, 3, 0.60546875, 0.4633553246018661, -47, -59, 0.849, 1.73),\n\t\tp(4, 3, 1, 0.6214021886400309, -33, 0, 0.377, 1.604),\n\t\tp(0, 4, -1, 1, 0, 0, 1, 1),\n\t\tp(1, 4, -0.5, 1, 0, -73, 1, 1),\n\t\tp(2, 4, -0.3271484375, 1, 0, -24, 0.314, 2.704),\n\t\tp(3, 4, 0.5, 1, 0, 0, 1, 1),\n\t\tp(4, 4, 1, 1, 0, 0, 1, 1),\n\t]),\n\tpreset(5, 5, [\n\t\tp(0, 0, -1, -1),\n\t\tp(1, 0, -0.6393, -1, 0, 0, 1, 2.3884),\n\t\tp(2, 0, 0, -1),\n\t\tp(3, 0, 0.5, -1),\n\t\tp(4, 0, 1, -1),\n\t\tp(0, 1, -1, -0.2301),\n\t\tp(1, 1, -0.6934, -0.331, 0, -0.7188, 1, 1.063),\n\t\tp(2, 1, -0.0082, -0.6814, -0.2583, 0, 1.0964, 1),\n\t\tp(3, 1, 0.5836, -0.531, 0.7029, 0, 1.5466, 1),\n\t\tp(4, 1, 1, -0.6407),\n\t\tp(0, 2, -1, 0.2973, 0, 0, 1.8352, 1),\n\t\tp(1, 2, -0.4082, 0.0602),\n\t\tp(2, 2, -0.1803, -0.3646, -0.2998, 0, 1.1513, 1),\n\t\tp(3, 2, 0.477, -0.1027, 0.8903, -0.1882, 1.0807, 0.8551),\n\t\tp(4, 2, 1, -0.2973),\n\t\tp(0, 3, -1, 0.7628, 0, 0, 2.3868, 1),\n\t\tp(1, 3, -0.2525, 0.4814, -0.8406, -1.6199, 1.4093, 1.2215),\n\t\tp(2, 3, 0.3607, 0.2814, -1.0713, -0.0529, 1.0025, 0.7611),\n\t\tp(3, 3, 0.4885, 0.623, 0, 0.8184, 1, 1.2876),\n\t\tp(4, 3, 1, 0.5),\n\t\tp(0, 4, -1, 1),\n\t\tp(1, 4, -0.4033, 1),\n\t\tp(2, 4, 0.2672, 1),\n\t\tp(3, 4, 0.5967, 1),\n\t\tp(4, 4, 1, 1),\n\t]),\n\tpreset(5, 5, [\n\t\tp(0, 0, -1, -1),\n\t\tp(1, 0, -0.2197, -1),\n\t\tp(2, 0, 0.0197, -1),\n\t\tp(3, 0, 0.8033, -1),\n\t\tp(4, 0, 1, -1),\n\t\tp(0, 1, -1, -0.5451),\n\t\tp(1, 1, -0.4885, -0.4035, -1.0246, -0.2268, 1.1936, 0.8005),\n\t\tp(2, 1, -0.1213, -0.2867, 0, -0.6981, 1, 0.809),\n\t\tp(3, 1, 0.3246, -0.5628, 0, -1.2188, 1, 1.044),\n\t\tp(4, 1, 1, -0.3292),\n\t\tp(0, 2, -1, 0.1416),\n\t\tp(1, 2, -0.341, -0.0142, 0, -0.4004, 1, 1.1293),\n\t\tp(2, 2, -0.0393, -0.023, 0.2915, -0.373, 1.044, 0.9879),\n\t\tp(3, 2, 0.3148, -0.0673, -0.7853, -0.8962, 1.4709, 1.0247),\n\t\tp(4, 2, 1, 0.1912),\n\t\tp(0, 3, -1, 0.5),\n\t\tp(1, 3, -0.2689, 0.2743, 0.3404, -0.5248, 1.0184, 0.4391),\n\t\tp(2, 3, 0.0721, 0.269, 0.5302, 0.1244, 0.6723, 0.3225),\n\t\tp(3, 3, 0.4148, 0.3894, -0.6977, -0.6783, 0.8094, 0.9247),\n\t\tp(4, 3, 1, 0.446),\n\t\tp(0, 4, -1, 1),\n\t\tp(1, 4, -0.7311, 1),\n\t\tp(2, 4, 0.323, 1),\n\t\tp(3, 4, 0.6393, 1),\n\t\tp(4, 4, 1, 1),\n\t]),\n] as const;\n","/**\n * @fileoverview\n * 实验性的随机控制点生成函数算法\n * 目的是取代原先大量的预设控制点代码\n */\n\nimport { clamp01 } from \"#utils/clamp.ts\";\nimport {\n\ttype ControlPointConf,\n\ttype ControlPointPreset,\n\tp,\n\tpreset,\n} from \"./cp-presets.ts\";\n\nconst randomRange = (min: number, max: number): number =>\n\tMath.random() * (max - min) + min;\n\nfunction smoothstep(edge0: number, edge1: number, x: number): number {\n\tconst t = clamp01((x - edge0) / (edge1 - edge0));\n\treturn t * t * (3 - 2 * t);\n}\n\nfunction smoothifyControlPoints(\n\tconf: ControlPointConf[],\n\tw: number,\n\th: number,\n\titerations = 2,\n\tfactor = 0.5,\n\tfactorIterationModifier = 0.1,\n): void {\n\tlet grid: ControlPointConf[][] = [];\n\tlet f = factor;\n\n\tfor (let j = 0; j < h; j++) {\n\t\tgrid[j] = [];\n\t\tfor (let i = 0; i < w; i++) {\n\t\t\tgrid[j][i] = conf[j * w + i];\n\t\t}\n\t}\n\n\tconst kernel = [\n\t\t[1, 2, 1],\n\t\t[2, 4, 2],\n\t\t[1, 2, 1],\n\t];\n\tconst kernelSum = 16;\n\n\tfor (let iter = 0; iter < iterations; iter++) {\n\t\tconst newGrid: ControlPointConf[][] = [];\n\t\tfor (let j = 0; j < h; j++) {\n\t\t\tnewGrid[j] = [];\n\t\t\tfor (let i = 0; i < w; i++) {\n\t\t\t\tif (i === 0 || i === w - 1 || j === 0 || j === h - 1) {\n\t\t\t\t\tnewGrid[j][i] = grid[j][i];\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlet sumX = 0;\n\t\t\t\tlet sumY = 0;\n\t\t\t\tlet sumUR = 0;\n\t\t\t\tlet sumVR = 0;\n\t\t\t\tlet sumUP = 0;\n\t\t\t\tlet sumVP = 0;\n\t\t\t\tfor (let dj = -1; dj <= 1; dj++) {\n\t\t\t\t\tfor (let di = -1; di <= 1; di++) {\n\t\t\t\t\t\tconst weight = kernel[dj + 1][di + 1];\n\t\t\t\t\t\tconst nb = grid[j + dj][i + di];\n\t\t\t\t\t\tsumX += nb.x * weight;\n\t\t\t\t\t\tsumY += nb.y * weight;\n\t\t\t\t\t\tsumUR += nb.ur * weight;\n\t\t\t\t\t\tsumVR += nb.vr * weight;\n\t\t\t\t\t\tsumUP += nb.up * weight;\n\t\t\t\t\t\tsumVP += nb.vp * weight;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst avgX = sumX / kernelSum;\n\t\t\t\tconst avgY = sumY / kernelSum;\n\t\t\t\tconst avgUR = sumUR / kernelSum;\n\t\t\t\tconst avgVR = sumVR / kernelSum;\n\t\t\t\tconst avgUP = sumUP / kernelSum;\n\t\t\t\tconst avgVP = sumVP / kernelSum;\n\n\t\t\t\tconst cur = grid[j][i];\n\t\t\t\tconst newX = cur.x * (1 - f) + avgX * f;\n\t\t\t\tconst newY = cur.y * (1 - f) + avgY * f;\n\t\t\t\tconst newUR = cur.ur * (1 - f) + avgUR * f;\n\t\t\t\tconst newVR = cur.vr * (1 - f) + avgVR * f;\n\t\t\t\tconst newUP = cur.up * (1 - f) + avgUP * f;\n\t\t\t\tconst newVP = cur.vp * (1 - f) + avgVP * f;\n\t\t\t\tnewGrid[j][i] = p(i, j, newX, newY, newUR, newVR, newUP, newVP);\n\t\t\t}\n\t\t}\n\t\tgrid = newGrid;\n\t\tf = clamp01(f + factorIterationModifier);\n\t}\n\n\tfor (let j = 0; j < h; j++) {\n\t\tfor (let i = 0; i < w; i++) {\n\t\t\tconf[j * w + i] = grid[j][i];\n\t\t}\n\t}\n}\n\nfunction noise(x: number, y: number): number {\n\treturn fract(Math.sin(x * 12.9898 + y * 78.233) * 43758.5453);\n}\n\nfunction fract(x: number): number {\n\treturn x - Math.floor(x);\n}\n\nfunction smoothNoise(x: number, y: number): number {\n\tconst x0 = Math.floor(x);\n\tconst y0 = Math.floor(y);\n\tconst x1 = x0 + 1;\n\tconst y1 = y0 + 1;\n\n\tconst xf = x - x0;\n\tconst yf = y - y0;\n\n\tconst u = xf * xf * (3 - 2 * xf);\n\tconst v = yf * yf * (3 - 2 * yf);\n\n\tconst n00 = noise(x0, y0);\n\tconst n10 = noise(x1, y0);\n\tconst n01 = noise(x0, y1);\n\tconst n11 = noise(x1, y1);\n\n\tconst nx0 = n00 * (1 - u) + n10 * u;\n\tconst nx1 = n01 * (1 - u) + n11 * u;\n\n\treturn nx0 * (1 - v) + nx1 * v;\n}\n\nfunction computeNoiseGradient(\n\tperlinFn: (x: number, y: number) => number,\n\tx: number,\n\ty: number,\n\tepsilon = 0.001,\n): [number, number] {\n\tconst n1 = perlinFn(x + epsilon, y);\n\tconst n2 = perlinFn(x - epsilon, y);\n\tconst n3 = perlinFn(x, y + epsilon);\n\tconst n4 = perlinFn(x, y - epsilon);\n\tconst dx = (n1 - n2) / (2 * epsilon);\n\tconst dy = (n3 - n4) / (2 * epsilon);\n\tconst len = Math.sqrt(dx * dx + dy * dy) || 1;\n\treturn [dx / len, dy / len];\n}\n\nexport function generateControlPoints(\n\twidth: number,\n\theight: number,\n\tvariationFraction: number = randomRange(0.4, 0.6), // = 0.2,\n\tnormalOffset: number = randomRange(0.3, 0.6), // = 0.3,\n\tblendFactor = 0.8,\n\tsmoothIters: number = Math.floor(randomRange(3, 5)), // = 3,\n\tsmoothFactor: number = randomRange(0.2, 0.3), // = 0.3,\n\tsmoothModifier: number = randomRange(-0.1, -0.05), // = -0.05,\n): ControlPointPreset {\n\tconst w = width ?? Math.floor(randomRange(3, 6));\n\tconst h = height ?? Math.floor(randomRange(3, 6));\n\n\tconst conf: ControlPointConf[] = [];\n\tconst dx = w === 1 ? 0 : 2 / (w - 1);\n\tconst dy = h === 1 ? 0 : 2 / (h - 1);\n\n\tfor (let j = 0; j < h; j++) {\n\t\tfor (let i = 0; i < w; i++) {\n\t\t\tconst baseX = (w === 1 ? 0 : i / (w - 1)) * 2 - 1;\n\t\t\tconst baseY = (h === 1 ? 0 : j / (h - 1)) * 2 - 1;\n\n\t\t\tconst isBorder = i === 0 || i === w - 1 || j === 0 || j === h - 1;\n\t\t\tconst pertX = isBorder\n\t\t\t\t? 0\n\t\t\t\t: randomRange(-variationFraction * dx, variationFraction * dx);\n\t\t\tconst pertY = isBorder\n\t\t\t\t? 0\n\t\t\t\t: randomRange(-variationFraction * dy, variationFraction * dy);\n\t\t\tlet x = baseX + pertX;\n\t\t\tlet y = baseY + pertY;\n\n\t\t\tconst ur = isBorder ? 0 : randomRange(-60, 60);\n\t\t\tconst vr = isBorder ? 0 : randomRange(-60, 60);\n\t\t\tconst up = isBorder ? 1 : randomRange(0.8, 1.2);\n\t\t\tconst vp = isBorder ? 1 : randomRange(0.8, 1.2);\n\n\t\t\tif (!isBorder) {\n\t\t\t\tconst uNorm = (baseX + 1) / 2;\n\t\t\t\tconst vNorm = (baseY + 1) / 2;\n\n\t\t\t\tconst [nx, ny] = computeNoiseGradient(smoothNoise, uNorm, vNorm, 0.001);\n\t\t\t\tlet offsetX = nx * normalOffset;\n\t\t\t\tlet offsetY = ny * normalOffset;\n\n\t\t\t\tconst distToBorder = Math.min(uNorm, 1 - uNorm, vNorm, 1 - vNorm); // in [0,0.5]\n\n\t\t\t\tconst weight = smoothstep(0, 1.0, distToBorder);\n\t\t\t\toffsetX *= weight;\n\t\t\t\toffsetY *= weight;\n\n\t\t\t\tx = x * (1 - blendFactor) + (x + offsetX) * blendFactor;\n\t\t\t\ty = y * (1 - blendFactor) + (y + offsetY) * blendFactor;\n\t\t\t}\n\t\t\tconf.push(p(i, j, x, y, ur, vr, up, vp));\n\t\t}\n\t}\n\n\tsmoothifyControlPoints(conf, w, h, smoothIters, smoothFactor, smoothModifier);\n\n\treturn preset(w, h, conf);\n}\n","/**\n * @fileoverview\n * 基于 Mesh Gradient 渐变渲染的渲染器\n * 此渲染应该是 Apple Music 使用的背景渲染方式了\n * 参考内容 https://movingparts.io/gradient-meshes\n */\n\nimport { Mat4, Vec2, Vec3, Vec4 } from \"gl-matrix\";\nimport type { Disposable } from \"../../interfaces.ts\";\nimport {\n\tloadResourceFromElement,\n\tloadResourceFromUrl,\n} from \"../../utils/resource.ts\";\nimport { BaseRenderer } from \"../base.ts\";\nimport { blurImage } from \"../img.ts\";\nimport { generateControlPoints } from \"./cp-generate.ts\";\nimport { CONTROL_POINT_PRESETS } from \"./cp-presets.ts\";\nimport meshFragShader from \"./mesh.frag.glsl?raw\";\nimport meshVertShader from \"./mesh.vert.glsl?raw\";\nimport { clamp01 } from \"#utils/clamp.ts\";\n\nconst quadVertShader = `\nattribute vec2 a_pos;\nvarying vec2 v_uv;\nvoid main() {\n gl_Position = vec4(a_pos, 0.0, 1.0);\n v_uv = a_pos * 0.5 + 0.5;\n}\n`;\n\nconst quadFragShader = `\nprecision mediump float;\nvarying vec2 v_uv;\nuniform sampler2D u_texture;\nuniform float u_alpha;\nvoid main() {\n vec4 color = texture2D(u_texture, v_uv);\n gl_FragColor = vec4(color.rgb, color.a * u_alpha);\n}\n`;\n\nfunction easeInOutSine(x: number): number {\n\treturn -(Math.cos(Math.PI * x) - 1) / 2;\n}\n\ntype RenderingContext = WebGLRenderingContext;\n\nclass GLProgram implements Disposable {\n\tprivate gl: RenderingContext;\n\tprogram: WebGLProgram;\n\tprivate vertexShader: WebGLShader;\n\tprivate fragmentShader: WebGLShader;\n\treadonly attrs: { [name: string]: number };\n\tconstructor(\n\t\tgl: RenderingContext,\n\t\tvertexShaderSource: string,\n\t\tfragmentShaderSource: string,\n\t\tprivate readonly label = \"unknown\",\n\t) {\n\t\tthis.gl = gl;\n\t\tthis.vertexShader = this.createShader(gl.VERTEX_SHADER, vertexShaderSource);\n\t\tthis.fragmentShader = this.createShader(\n\t\t\tgl.FRAGMENT_SHADER,\n\t\t\tfragmentShaderSource,\n\t\t);\n\t\tthis.program = this.createProgram();\n\n\t\tconst num = gl.getProgramParameter(this.program, gl.ACTIVE_ATTRIBUTES);\n\t\tconst attrs: { [name: string]: number } = {};\n\t\tfor (let i = 0; i < num; i++) {\n\t\t\tconst info = gl.getActiveAttrib(this.program, i);\n\t\t\tif (!info) continue;\n\t\t\tconst location = gl.getAttribLocation(this.program, info.name);\n\t\t\tif (location === -1) continue;\n\t\t\tattrs[info.name] = location;\n\t\t}\n\t\tthis.attrs = attrs;\n\t}\n\tprivate createShader(type: number, source: string) {\n\t\tconst gl = this.gl;\n\t\tconst shader = gl.createShader(type);\n\t\tif (!shader) throw new Error(\"Failed to create shader\");\n\t\tgl.shaderSource(shader, source);\n\t\tgl.compileShader(shader);\n\t\tif (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to compile shader for type ${type} \"${\n\t\t\t\t\tthis.label\n\t\t\t\t}\": ${gl.getShaderInfoLog(shader)}`,\n\t\t\t);\n\t\t}\n\t\treturn shader;\n\t}\n\tprivate createProgram() {\n\t\tconst gl = this.gl;\n\t\tconst program = gl.createProgram();\n\t\tif (!program) throw new Error(\"Failed to create program\");\n\t\tgl.attachShader(program, this.vertexShader);\n\t\tgl.attachShader(program, this.fragmentShader);\n\t\tgl.linkProgram(program);\n\t\tgl.validateProgram(program);\n\t\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\t\tconst errLog = gl.getProgramInfoLog(program);\n\t\t\tgl.deleteProgram(program);\n\t\t\tthrow new Error(`Failed to link program \"${this.label}\": ${errLog}`);\n\t\t}\n\t\treturn program;\n\t}\n\tuse() {\n\t\tconst gl = this.gl;\n\t\tgl.useProgram(this.program);\n\t}\n\tprivate notFoundUniforms: Set<string> = new Set();\n\tprivate warnUniformNotFound(name: string) {\n\t\tif (this.notFoundUniforms.has(name)) return;\n\t\tthis.notFoundUniforms.add(name);\n\t\tconsole.warn(\n\t\t\t`Failed to get uniform location for program \"${this.label}\": ${name}`,\n\t\t);\n\t}\n\tsetUniform1f(name: string, value: number) {\n\t\tconst gl = this.gl;\n\t\tconst location = gl.getUniformLocation(this.program, name);\n\t\tif (!location) this.warnUniformNotFound(name);\n\t\telse gl.uniform1f(location, value);\n\t}\n\tsetUniform2f(name: string, value1: number, value2: number) {\n\t\tconst gl = this.gl;\n\t\tconst location = gl.getUniformLocation(this.program, name);\n\t\tif (!location) this.warnUniformNotFound(name);\n\t\telse gl.uniform2f(location, value1, value2);\n\t}\n\tsetUniform1i(name: string, value: number) {\n\t\tconst gl = this.gl;\n\t\tconst location = gl.getUniformLocation(this.program, name);\n\t\tif (!location) this.warnUniformNotFound(name);\n\t\telse gl.uniform1i(location, value);\n\t}\n\tdispose() {\n\t\tconst gl = this.gl;\n\t\tgl.deleteShader(this.vertexShader);\n\t\tgl.deleteShader(this.fragmentShader);\n\t\tgl.deleteProgram(this.program);\n\t}\n}\n\nclass Mesh implements Disposable {\n\tprotected vertexWidth = 0;\n\tprotected vertexHeight = 0;\n\tprivate vertexBuffer: WebGLBuffer;\n\tprivate indexBuffer: WebGLBuffer;\n\tprivate vertexData: Float32Array;\n\tprivate indexData: Uint16Array;\n\tprivate vertexIndexLength = 0;\n\t// 调试用途,开启线框模式\n\tprivate wireFrame = false;\n\tconstructor(\n\t\tprivate readonly gl: RenderingContext,\n\t\tprivate readonly attrPos: number | undefined,\n\t\tprivate readonly attrColor: number | undefined,\n\t\tprivate readonly attrUV: number | undefined,\n\t) {\n\t\tconst vertexBuf = gl.createBuffer();\n\t\tif (!vertexBuf) throw new Error(\"Failed to create vertex buffer\");\n\t\tthis.vertexBuffer = vertexBuf;\n\t\tconst indexBuf = gl.createBuffer();\n\t\tif (!indexBuf) throw new Error(\"Failed to create index buffer\");\n\t\tthis.indexBuffer = indexBuf;\n\n\t\tthis.bind();\n\n\t\tthis.vertexData = new Float32Array(0);\n\t\tthis.indexData = new Uint16Array(0);\n\n\t\tthis.resize(2, 2);\n\t\tthis.update();\n\t}\n\n\tsetWireFrame(enable: boolean) {\n\t\tthis.wireFrame = enable;\n\t\tthis.resize(this.vertexWidth, this.vertexHeight);\n\t}\n\n\tsetVertexPos(vx: number, vy: number, x: number, y: number): void {\n\t\tconst idx = (vx + vy * this.vertexWidth) * 7;\n\t\tif (idx >= this.vertexData.length - 1) {\n\t\t\tconsole.warn(\"Vertex position out of range\", idx, this.vertexData.length);\n\t\t\treturn;\n\t\t}\n\t\tthis.vertexData[idx] = x;\n\t\tthis.vertexData[idx + 1] = y;\n\t}\n\n\tsetVertexColor(\n\t\tvx: number,\n\t\tvy: number,\n\t\tr: number,\n\t\tg: number,\n\t\tb: number,\n\t): void {\n\t\tconst idx = (vx + vy * this.vertexWidth) * 7 + 2;\n\t\tif (idx >= this.vertexData.length - 2) {\n\t\t\tconsole.warn(\"Vertex color out of range\", idx, this.vertexData.length);\n\t\t\treturn;\n\t\t}\n\t\tthis.vertexData[idx] = r;\n\t\tthis.vertexData[idx + 1] = g;\n\t\tthis.vertexData[idx + 2] = b;\n\t}\n\n\tsetVertexUV(vx: number, vy: number, x: number, y: number): void {\n\t\tconst idx = (vx + vy * this.vertexWidth) * 7 + 5;\n\t\tif (idx >= this.vertexData.length - 1) {\n\t\t\tconsole.warn(\"Vertex UV out of range\", idx, this.vertexData.length);\n\t\t\treturn;\n\t\t}\n\t\tthis.vertexData[idx] = x;\n\t\tthis.vertexData[idx + 1] = y;\n\t}\n\n\t// 批量设置顶点数据的优化方法\n\tsetVertexData(\n\t\tvx: number,\n\t\tvy: number,\n\t\tx: number,\n\t\ty: number,\n\t\tr: number,\n\t\tg: number,\n\t\tb: number,\n\t\tu: number,\n\t\tv: number,\n\t): void {\n\t\tconst idx = (vx + vy * this.vertexWidth) * 7;\n\t\tif (idx >= this.vertexData.length - 6) {\n\t\t\tconsole.warn(\"Vertex data out of range\", idx, this.vertexData.length);\n\t\t\treturn;\n\t\t}\n\t\tconst data = this.vertexData;\n\t\tdata[idx] = x;\n\t\tdata[idx + 1] = y;\n\t\tdata[idx + 2] = r;\n\t\tdata[idx + 3] = g;\n\t\tdata[idx + 4] = b;\n\t\tdata[idx + 5] = u;\n\t\tdata[idx + 6] = v;\n\t}\n\n\tgetVertexIndexLength(): number {\n\t\treturn this.vertexIndexLength;\n\t}\n\n\tdraw() {\n\t\tconst gl = this.gl;\n\n\t\tif (this.wireFrame) {\n\t\t\tgl.drawElements(gl.LINES, this.vertexIndexLength, gl.UNSIGNED_SHORT, 0);\n\t\t} else {\n\t\t\tgl.drawElements(\n\t\t\t\tgl.TRIANGLES,\n\t\t\t\tthis.vertexIndexLength,\n\t\t\t\tgl.UNSIGNED_SHORT,\n\t\t\t\t0,\n\t\t\t);\n\t\t}\n\t}\n\n\tresize(vertexWidth: number, vertexHeight: number): void {\n\t\tthis.vertexWidth = vertexWidth;\n\t\tthis.vertexHeight = vertexHeight;\n\t\t// 2 个顶点坐标 + 3 个颜色值 + 2 个 UV 坐标\n\t\tthis.vertexIndexLength = vertexWidth * vertexHeight * 6;\n\t\tif (this.wireFrame) {\n\t\t\tthis.vertexIndexLength = vertexWidth * vertexHeight * 10;\n\t\t}\n\t\tconst vertexData = new Float32Array(\n\t\t\tvertexWidth * vertexHeight * (2 + 3 + 2),\n\t\t);\n\t\tconst indexData = new Uint16Array(this.vertexIndexLength);\n\t\tthis.vertexData = vertexData;\n\t\tthis.indexData = indexData;\n\t\tfor (let y = 0; y < vertexHeight; y++) {\n\t\t\tfor (let x = 0; x < vertexWidth; x++) {\n\t\t\t\tconst px = (x / (vertexWidth - 1)) * 2 - 1;\n\t\t\t\tconst py = (y / (vertexHeight - 1)) * 2 - 1;\n\t\t\t\tthis.setVertexPos(x, y, px || 0, py || 0);\n\t\t\t\tthis.setVertexColor(x, y, 1, 1, 1);\n\t\t\t\tthis.setVertexUV(x, y, x / (vertexWidth - 1), y / (vertexHeight - 1));\n\t\t\t}\n\t\t}\n\t\tfor (let y = 0; y < vertexHeight - 1; y++) {\n\t\t\tfor (let x = 0; x < vertexWidth - 1; x++) {\n\t\t\t\tif (this.wireFrame) {\n\t\t\t\t\tconst idx = (y * vertexWidth + x) * 10;\n\n\t\t\t\t\tindexData[idx] = y * vertexWidth + x;\n\t\t\t\t\tindexData[idx + 1] = y * vertexWidth + x + 1;\n\n\t\t\t\t\tindexData[idx + 2] = y * vertexWidth + x + 1;\n\t\t\t\t\tindexData[idx + 3] = (y + 1) * vertexWidth + x;\n\n\t\t\t\t\tindexData[idx + 4] = (y + 1) * vertexWidth + x;\n\t\t\t\t\tindexData[idx + 5] = (y + 1) * vertexWidth + x + 1;\n\n\t\t\t\t\tindexData[idx + 6] = (y + 1) * vertexWidth + x + 1;\n\t\t\t\t\tindexData[idx + 7] = y * vertexWidth + x + 1;\n\n\t\t\t\t\tindexData[idx + 8] = y * vertexWidth + x;\n\t\t\t\t\tindexData[idx + 9] = (y + 1) * vertexWidth + x;\n\t\t\t\t} else {\n\t\t\t\t\tconst idx = (y * vertexWidth + x) * 6;\n\t\t\t\t\tindexData[idx] = y * vertexWidth + x;\n\t\t\t\t\tindexData[idx + 1] = y * vertexWidth + x + 1;\n\t\t\t\t\tindexData[idx + 2] = (y + 1) * vertexWidth + x;\n\t\t\t\t\tindexData[idx + 3] = y * vertexWidth + x + 1;\n\t\t\t\t\tindexData[idx + 4] = (y + 1) * vertexWidth + x + 1;\n\t\t\t\t\tindexData[idx + 5] = (y + 1) * vertexWidth + x;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst gl = this.gl;\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);\n\t\tgl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indexData, gl.STATIC_DRAW);\n\t}\n\n\tbind() {\n\t\tconst gl = this.gl;\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);\n\n\t\tif (this.attrPos !== undefined) {\n\t\t\tgl.vertexAttribPointer(this.attrPos, 2, gl.FLOAT, false, 4 * 7, 0);\n\t\t\tgl.enableVertexAttribArray(this.attrPos);\n\t\t}\n\t\tif (this.attrColor !== undefined) {\n\t\t\tgl.vertexAttribPointer(this.attrColor, 3, gl.FLOAT, false, 4 * 7, 4 * 2);\n\t\t\tgl.enableVertexAttribArray(this.attrColor);\n\t\t}\n\t\tif (this.attrUV !== undefined) {\n\t\t\tgl.vertexAttribPointer(this.attrUV, 2, gl.FLOAT, false, 4 * 7, 4 * 5);\n\t\t\tgl.enableVertexAttribArray(this.attrUV);\n\t\t}\n\t}\n\n\tupdate() {\n\t\tconst gl = this.gl;\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, this.vertexData, gl.DYNAMIC_DRAW);\n\t}\n\n\tdispose(): void {\n\t\tthis.gl.deleteBuffer(this.vertexBuffer);\n\t\tthis.gl.deleteBuffer(this.indexBuffer);\n\t}\n}\n\nclass ControlPoint {\n\tcolor: Vec3 = Vec3.fromValues(1, 1, 1);\n\tlocation: Vec2 = Vec2.fromValues(0, 0);\n\tuTangent: Vec2 = Vec2.fromValues(0, 0);\n\tvTangent: Vec2 = Vec2.fromValues(0, 0);\n\tprivate _uRot = 0;\n\tprivate _vRot = 0;\n\tprivate _uScale = 1;\n\tprivate _vScale = 1;\n\n\tconstructor() {\n\t\tObject.seal(this);\n\t}\n\n\tget uRot() {\n\t\treturn this._uRot;\n\t}\n\n\tget vRot() {\n\t\treturn this._vRot;\n\t}\n\n\tset uRot(value: number) {\n\t\tthis._uRot = value;\n\t\tthis.updateUTangent();\n\t}\n\n\tset vRot(value: number) {\n\t\tthis._vRot = value;\n\t\tthis.updateVTangent();\n\t}\n\n\tget uScale() {\n\t\treturn this._uScale;\n\t}\n\n\tget vScale() {\n\t\treturn this._vScale;\n\t}\n\n\tset uScale(value: number) {\n\t\tthis._uScale = value;\n\t\tthis.updateUTangent();\n\t}\n\n\tset vScale(value: number) {\n\t\tthis._vScale = value;\n\t\tthis.updateVTangent();\n\t}\n\n\tprivate updateUTangent() {\n\t\tthis.uTangent[0] = Math.cos(this._uRot) * this._uScale;\n\t\tthis.uTangent[1] = Math.sin(this._uRot) * this._uScale;\n\t}\n\n\tprivate updateVTangent() {\n\t\tthis.vTangent[0] = -Math.sin(this._vRot) * this._vScale;\n\t\tthis.vTangent[1] = Math.cos(this._vRot) * this._vScale;\n\t}\n}\n\nconst H = Mat4.fromValues(2, -2, 1, 1, -3, 3, -2, -1, 0, 0, 1, 0, 1, 0, 0, 0);\nconst H_T = Mat4.clone(H).transpose();\n\nfunction meshCoefficients(\n\tp00: ControlPoint,\n\tp01: ControlPoint,\n\tp10: ControlPoint,\n\tp11: ControlPoint,\n\taxis: \"x\" | \"y\",\n\toutput = Mat4.create(),\n): Mat4 {\n\tconst l = (p: ControlPoint) => p.location[axis];\n\tconst u = (p: ControlPoint) => p.uTangent[axis];\n\tconst v = (p: ControlPoint) => p.vTangent[axis];\n\n\toutput[0] = l(p00);\n\toutput[1] = l(p01);\n\toutput[2] = v(p00);\n\toutput[3] = v(p01);\n\toutput[4] = l(p10);\n\toutput[5] = l(p11);\n\toutput[6] = v(p10);\n\toutput[7] = v(p11);\n\toutput[8] = u(p00);\n\toutput[9] = u(p01);\n\toutput[10] = 0;\n\toutput[11] = 0;\n\toutput[12] = u(p10);\n\toutput[13] = u(p11);\n\toutput[14] = 0;\n\toutput[15] = 0;\n\n\treturn output;\n}\n\nfunction colorCoefficients(\n\tp00: ControlPoint,\n\tp01: ControlPoint,\n\tp10: ControlPoint,\n\tp11: ControlPoint,\n\taxis: \"r\" | \"g\" | \"b\",\n\toutput = Mat4.create(),\n): Mat4 {\n\tconst c = (p: ControlPoint) => p.color[axis];\n\toutput.fill(0);\n\toutput[0] = c(p00);\n\toutput[1] = c(p01);\n\toutput[4] = c(p10);\n\toutput[5] = c(p11);\n\t// return Mat4.fromValues(\n\t// c(p00), c(p01), 0, 0,\n\t// c(p10), c(p11), 0, 0,\n\t// 0, 0, 0, 0,\n\t// 0, 0, 0, 0,\n\t// );\n\treturn output;\n}\n\nclass Map2D<T> {\n\tprivate _width = 0;\n\tprivate _height = 0;\n\tprivate _data: T[] = [];\n\tconstructor(width: number, height: number) {\n\t\tthis.resize(width, height);\n\t\tObject.seal(this);\n\t}\n\tresize(width: number, height: number) {\n\t\tthis._width = width;\n\t\tthis._height = height;\n\t\tthis._data = new Array(width * height).fill(0);\n\t}\n\tset(x: number, y: number, value: T) {\n\t\tthis._data[x + y * this._width] = value;\n\t}\n\tget(x: number, y: number) {\n\t\treturn this._data[x + y * this._width];\n\t}\n\tget width() {\n\t\treturn this._width;\n\t}\n\tget height() {\n\t\treturn this._height;\n\t}\n}\n\n// Bicubic Hermite Patch Mesh\nclass BHPMesh extends Mesh {\n\t/**\n\t * 细分级别,越大曲线越平滑,但是性能消耗也越大\n\t */\n\tprivate _subDivisions = 10;\n\tprivate _controlPoints: Map2D<ControlPoint> = new Map2D(3, 3);\n\n\tconstructor(\n\t\tgl: RenderingContext,\n\t\tattrPos: number,\n\t\tattrColor: number,\n\t\tattrUV: number,\n\t) {\n\t\tsuper(gl, attrPos, attrColor, attrUV);\n\t\tthis.resizeControlPoints(3, 3);\n\t\tObject.seal(this);\n\t}\n\toverride setWireFrame(enable: boolean) {\n\t\tsuper.setWireFrame(enable);\n\t\tthis.updateMesh();\n\t}\n\t/**\n\t * 以当前的控制点矩阵大小和细分级别为参考重新设置细分级别,此操作不会重设控制点数据\n\t * @param subDivisions 细分级别\n\t */\n\tresetSubdivition(subDivisions: number) {\n\t\tthis._subDivisions = subDivisions;\n\t\tsuper.resize(\n\t\t\t(this._controlPoints.width - 1) * subDivisions,\n\t\t\t(this._controlPoints.height - 1) * subDivisions,\n\t\t);\n\t}\n\t/**\n\t * 重设控制点矩阵尺寸,将会重置所有控制点的颜色和坐标数据\n\t * 请在调用此方法后重新设置颜色和坐标,并调用 updateMesh 方法更新网格\n\t * @param width 控制点宽度数量,必须大于等于 2\n\t * @param height 控制点高度数量,必须大于等于 2\n\t */\n\tresizeControlPoints(width: number, height: number) {\n\t\tif (!(width >= 2 && height >= 2)) {\n\t\t\tthrow new Error(\"Control points must be larger than 3x3 or equal\");\n\t\t}\n\t\tthis._controlPoints.resize(width, height);\n\t\tfor (let y = 0; y < height; y++) {\n\t\t\tfor (let x = 0; x < width; x++) {\n\t\t\t\tconst point = new ControlPoint();\n\t\t\t\tpoint.location.x = (x / (width - 1)) * 2 - 1;\n\t\t\t\tpoint.location.y = (y / (height - 1)) * 2 - 1;\n\t\t\t\tpoint.uTangent.x = 2 / (width - 1);\n\t\t\t\tpoint.vTangent.y = 2 / (height - 1);\n\t\t\t\tthis._controlPoints.set(x, y, point);\n\t\t\t}\n\t\t}\n\t\tthis.resetSubdivition(this._subDivisions);\n\t}\n\t/**\n\t * 获取指定位置的控制点,然后可以设置颜色和坐标属性\n\t * 留意颜色属性和坐标属性的值范围均参考 WebGL 的定义\n\t * 即颜色各个组件取值 [0-1],坐标取值 [-1, 1]\n\t * 点的位置以画面左下角为原点 (0,0)\n\t * @param x 需要获取的控制点的 x 坐标\n\t * @param y 需要获取的控制点的 y 坐标\n\t * @returns 控制点对象\n\t */\n\tgetControlPoint(x: number, y: number) {\n\t\treturn this._controlPoints.get(x, y);\n\t}\n\t// 预分配重复使用的矩阵,避免频繁创建\n\tprivate tempX = Mat4.create();\n\tprivate tempY = Mat4.create();\n\tprivate tempR = Mat4.create();\n\tprivate tempG = Mat4.create();\n\tprivate tempB = Mat4.create();\n\n\tprivate tempXAcc = Mat4.create();\n\tprivate tempYAcc = Mat4.create();\n\tprivate tempRAcc = Mat4.create();\n\tprivate tempGAcc = Mat4.create();\n\tprivate tempBAcc = Mat4.create();\n\n\tprivate tempUx = Vec4.create();\n\tprivate tempUy = Vec4.create();\n\tprivate tempUr = Vec4.create();\n\tprivate tempUg = Vec4.create();\n\tprivate tempUb = Vec4.create();\n\n\tprivate precomputeMatrix(M: Mat4, output: Mat4) {\n\t\toutput.copy(M).transpose();\n\t\tMat4.mul(output, output, H);\n\t\tMat4.mul(output, H_T, output);\n\t\treturn output;\n\t}\n\n\t/**\n\t * 更新最终呈现的网格数据,此方法应在所有控制点或细分参数的操作完成后调用\n\t */\n\tupdateMesh() {\n\t\tconst subDivM1 = this._subDivisions - 1;\n\t\tconst tW = subDivM1 * (this._controlPoints.height - 1);\n\t\tconst tH = subDivM1 * (this._controlPoints.width - 1);\n\t\tconst controlPointsWidth = this._controlPoints.width;\n\t\tconst controlPointsHeight = this._controlPoints.height;\n\t\tconst subDivisions = this._subDivisions;\n\n\t\t// 预计算常用值\n\t\tconst invSubDivM1 = 1 / subDivM1;\n\t\tconst invTH = 1 / tH;\n\t\tconst invTW = 1 / tW;\n\n\t\t// 预计算 u 和 v 的幂次\n\t\tconst normPowers = new Float32Array(subDivisions * 4);\n\t\tfor (let i = 0; i < subDivisions; i++) {\n\t\t\tconst norm = i * invSubDivM1;\n\t\t\tconst idx = i * 4;\n\t\t\tnormPowers[idx] = norm ** 3;\n\t\t\tnormPowers[idx + 1] = norm ** 2;\n\t\t\tnormPowers[idx + 2] = norm;\n\t\t\tnormPowers[idx + 3] = 1;\n\t\t}\n\n\t\tfor (let x = 0; x < controlPointsWidth - 1; x++) {\n\t\t\tfor (let y = 0; y < controlPointsHeight - 1; y++) {\n\t\t\t\tconst p00 = this._controlPoints.get(x, y);\n\t\t\t\tconst p01 = this._controlPoints.get(x, y + 1);\n\t\t\t\tconst p10 = this._controlPoints.get(x + 1, y);\n\t\t\t\tconst p11 = this._controlPoints.get(x + 1, y + 1);\n\n\t\t\t\t// 复用预分配的矩阵\n\t\t\t\tmeshCoefficients(p00, p01, p10, p11, \"x\", this.tempX);\n\t\t\t\tmeshCoefficients(p00, p01, p10, p11, \"y\", this.tempY);\n\t\t\t\tcolorCoefficients(p00, p01, p10, p11, \"r\", this.tempR);\n\t\t\t\tcolorCoefficients(p00, p01, p10, p11, \"g\", this.tempG);\n\t\t\t\tcolorCoefficients(p00, p01, p10, p11, \"b\", this.tempB);\n\n\t\t\t\t// 预计算累加矩阵\n\t\t\t\tthis.precomputeMatrix(this.tempX, this.tempXAcc);\n\t\t\t\tthis.precomputeMatrix(this.tempY, this.tempYAcc);\n\t\t\t\tthis.precomputeMatrix(this.tempR, this.tempRAcc);\n\t\t\t\tthis.precomputeMatrix(this.tempG, this.tempGAcc);\n\t\t\t\tthis.precomputeMatrix(this.tempB, this.tempBAcc);\n\n\t\t\t\tconst sX = x / (controlPointsWidth - 1);\n\t\t\t\tconst sY = y / (controlPointsHeight - 1);\n\t\t\t\tconst baseVx = y * subDivisions;\n\t\t\t\tconst baseVy = x * subDivisions;\n\n\t\t\t\tfor (let u = 0; u < subDivisions; u++) {\n\t\t\t\t\tconst vxOffset = baseVx + u;\n\t\t\t\t\tconst uIdx = u * 4;\n\n\t\t\t\t\tthis.tempUx[0] = normPowers[uIdx];\n\t\t\t\t\tthis.tempUx[1] = normPowers[uIdx + 1];\n\t\t\t\t\tthis.tempUx[2] = normPowers[uIdx + 2];\n\t\t\t\t\tthis.tempUx[3] = normPowers[uIdx + 3];\n\t\t\t\t\tVec4.transformMat4(this.tempUx, this.tempUx, this.tempXAcc);\n\n\t\t\t\t\tthis.tempUy[0] = normPowers[uIdx];\n\t\t\t\t\tthis.tempUy[1] = normPowers[uIdx + 1];\n\t\t\t\t\tthis.tempUy[2] = normPowers[uIdx + 2];\n\t\t\t\t\tthis.tempUy[3] = normPowers[uIdx + 3];\n\t\t\t\t\tVec4.transformMat4(this.tempUy, this.tempUy, this.tempYAcc);\n\n\t\t\t\t\tthis.tempUr[0] = normPowers[uIdx];\n\t\t\t\t\tthis.tempUr[1] = normPowers[uIdx + 1];\n\t\t\t\t\tthis.tempUr[2] = normPowers[uIdx + 2];\n\t\t\t\t\tthis.tempUr[3] = normPowers[uIdx + 3];\n\t\t\t\t\tVec4.transformMat4(this.tempUr, this.tempUr, this.tempRAcc);\n\n\t\t\t\t\tthis.tempUg[0] = normPowers[uIdx];\n\t\t\t\t\tthis.tempUg[1] = normPowers[uIdx + 1];\n\t\t\t\t\tthis.tempUg[2] = normPowers[uIdx + 2];\n\t\t\t\t\tthis.tempUg[3] = normPowers[uIdx + 3];\n\t\t\t\t\tVec4.transformMat4(this.tempUg, this.tempUg, this.tempGAcc);\n\n\t\t\t\t\tthis.tempUb[0] = normPowers[uIdx];\n\t\t\t\t\tthis.tempUb[1] = normPowers[uIdx + 1];\n\t\t\t\t\tthis.tempUb[2] = normPowers[uIdx + 2];\n\t\t\t\t\tthis.tempUb[3] = normPowers[uIdx + 3];\n\t\t\t\t\tVec4.transformMat4(this.tempUb, this.tempUb, this.tempBAcc);\n\n\t\t\t\t\tfor (let v = 0; v < subDivisions; v++) {\n\t\t\t\t\t\tconst vy = baseVy + v;\n\t\t\t\t\t\tconst vIdx = v * 4;\n\n\t\t\t\t\t\tconst v0 = normPowers[vIdx];\n\t\t\t\t\t\tconst v1 = normPowers[vIdx + 1];\n\t\t\t\t\t\tconst v2 = normPowers[vIdx + 2];\n\t\t\t\t\t\tconst v3 = normPowers[vIdx + 3];\n\n\t\t\t\t\t\tconst px =\n\t\t\t\t\t\t\tv0 * this.tempUx[0] +\n\t\t\t\t\t\t\tv1 * this.tempUx[1] +\n\t\t\t\t\t\t\tv2 * this.tempUx[2] +\n\t\t\t\t\t\t\tv3 * this.tempUx[3];\n\t\t\t\t\t\tconst py =\n\t\t\t\t\t\t\tv0 * this.tempUy[0] +\n\t\t\t\t\t\t\tv1 * this.tempUy[1] +\n\t\t\t\t\t\t\tv2 * this.tempUy[2] +\n\t\t\t\t\t\t\tv3 * this.tempUy[3];\n\t\t\t\t\t\tconst pr =\n\t\t\t\t\t\t\tv0 * this.tempUr[0] +\n\t\t\t\t\t\t\tv1 * this.tempUr[1] +\n\t\t\t\t\t\t\tv2 * this.tempUr[2] +\n\t\t\t\t\t\t\tv3 * this.tempUr[3];\n\t\t\t\t\t\tconst pg =\n\t\t\t\t\t\t\tv0 * this.tempUg[0] +\n\t\t\t\t\t\t\tv1 * this.tempUg[1] +\n\t\t\t\t\t\t\tv2 * this.tempUg[2] +\n\t\t\t\t\t\t\tv3 * this.tempUg[3];\n\t\t\t\t\t\tconst pb =\n\t\t\t\t\t\t\tv0 * this.tempUb[0] +\n\t\t\t\t\t\t\tv1 * this.tempUb[1] +\n\t\t\t\t\t\t\tv2 * this.tempUb[2] +\n\t\t\t\t\t\t\tv3 * this.tempUb[3];\n\n\t\t\t\t\t\tconst uvX = sX + v * invTH;\n\t\t\t\t\t\tconst uvY = 1 - sY - u * invTW;\n\n\t\t\t\t\t\t// 使用批量设置方法减少数组访问次数\n\t\t\t\t\t\tthis.setVertexData(vxOffset, vy, px, py, pr, pg, pb, uvX, uvY);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.update();\n\t}\n}\n\nclass GLTexture implements Disposable {\n\treadonly tex: WebGLTexture;\n\n\tconstructor(\n\t\tprivate gl: WebGLRenderingContext,\n\t\talbumImageData: ImageData,\n\t) {\n\t\tconst albumTexture = gl.createTexture();\n\t\tif (!albumTexture) throw new Error(\"Failed to create texture\");\n\t\tthis.tex = albumTexture;\n\t\tgl.activeTexture(gl.TEXTURE0);\n\t\tgl.bindTexture(gl.TEXTURE_2D, albumTexture);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\talbumImageData,\n\t\t);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);\n\t}\n\n\tbind() {\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, this.tex);\n\t}\n\n\tdispose(): void {\n\t\tthis.gl.deleteTexture(this.tex);\n\t}\n}\n\nfunction createOffscreenCanvas(width: number, height: number) {\n\tif (\"OffscreenCanvas\" in window) return new OffscreenCanvas(width, height);\n\tconst canvas = document.createElement(\"canvas\");\n\tcanvas.width = width;\n\tcanvas.height = height;\n\treturn canvas;\n}\n\ninterface MeshState {\n\tmesh: BHPMesh;\n\ttexture: GLTexture;\n\talpha: number;\n}\n\nexport class MeshGradientRenderer extends BaseRenderer {\n\tprivate gl: RenderingContext;\n\tprivate lastFrameTime = 0;\n\tprivate frameTime = 0;\n\t// private currentImageData?: ImageData;\n\tprivate lastTickTime = 0;\n\tprivate smoothedVolume = 0;\n\tprivate volume = 0;\n\tprivate tickHandle = 0;\n\tprivate maxFPS = 60;\n\tprivate paused = false;\n\tprivate staticMode = false;\n\tprivate mainProgram: GLProgram;\n\tprivate quadProgram: GLProgram;\n\tprivate quadBuffer: WebGLBuffer;\n\tprivate fbo: WebGLFramebuffer | null = null;\n\tprivate fboTexture: WebGLTexture | null = null;\n\tprivate manualControl = false;\n\tprivate reduceImageSizeCanvas = createOffscreenCanvas(\n\t\t32,\n\t\t32,\n\t) as HTMLCanvasElement;\n\tprivate targetSize = Vec2.fromValues(0, 0);\n\tprivate currentSize = Vec2.fromValues(0, 0);\n\tprivate isNoCover = true;\n\tprivate meshStates: MeshState[] = [];\n\tprivate _disposed = false;\n\t// 性能监控\n\tprivate frameCount = 0;\n\tprivate lastFPSUpdate = 0;\n\tprivate currentFPS = 0;\n\tprivate enablePerformanceMonitoring = false;\n\n\tsetManualControl(enable: boolean): void {\n\t\tthis.manualControl = enable;\n\t}\n\n\tsetWireFrame(enable: boolean): void {\n\t\tfor (const state of this.meshStates) {\n\t\t\tstate.mesh.setWireFrame(enable);\n\t\t}\n\t}\n\n\tgetControlPoint(x: number, y: number): ControlPoint | undefined {\n\t\treturn this.meshStates[this.meshStates.length - 1]?.mesh?.getControlPoint(\n\t\t\tx,\n\t\t\ty,\n\t\t);\n\t}\n\n\tresizeControlPoints(width: number, height: number): void {\n\t\tthis.meshStates[this.meshStates.length - 1]?.mesh?.resizeControlPoints(\n\t\t\twidth,\n\t\t\theight,\n\t\t);\n\t}\n\n\tresetSubdivition(subDivisions: number): void {\n\t\tthis.meshStates[this.meshStates.length - 1]?.mesh?.resetSubdivition(\n\t\t\tsubDivisions,\n\t\t);\n\t}\n\n\tprivate onTick(tickTime: number) {\n\t\tthis.tickHandle = 0;\n\t\tif (this.paused) return;\n\t\tif (this._disposed) return;\n\n\t\t// 更新性能统计\n\t\tthis.updatePerformanceStats(tickTime);\n\n\t\tconst interval = 1000 / this.maxFPS;\n\t\tconst delta = tickTime - this.lastTickTime;\n\t\tif (delta < interval) {\n\t\t\tthis.requestTick();\n\t\t\treturn;\n\t\t}\n\n\t\tif (Number.isNaN(this.lastFrameTime)) {\n\t\t\tthis.lastFrameTime = tickTime;\n\t\t}\n\t\tconst frameDelta = tickTime - this.lastFrameTime;\n\t\tthis.lastFrameTime = tickTime;\n\t\t// 减去多余的时间,避免帧率漂移(例如高刷显示器限制低帧率时)\n\t\tthis.lastTickTime = tickTime - (delta % interval);\n\n\t\tthis.frameTime += frameDelta * this.flowSpeed;\n\n\t\tif (!(this.onRedraw(this.frameTime, frameDelta) && this.staticMode)) {\n\t\t\tthis.requestTick();\n\t\t} else if (this.staticMode) {\n\t\t\tthis.lastFrameTime = Number.NaN;\n\t\t}\n\t}\n\n\tprivate checkIfResize() {\n\t\tconst [tW, tH] = [this.targetSize.x, this.targetSize.y];\n\t\tconst [cW, cH] = [this.currentSize.x, this.currentSize.y];\n\t\tif (tW !== cW || tH !== cH) {\n\t\t\tsuper.onResize(tW, tH);\n\t\t\tconst gl = this.gl;\n\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\t\tgl.viewport(0, 0, tW, tH);\n\t\t\tthis.currentSize.x = tW;\n\t\t\tthis.currentSize.y = tH;\n\t\t\tif (tW > 0 && tH > 0) {\n\t\t\t\tthis.updateFBO(tW, tH);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate updateFBO(width: number, height: number) {\n\t\tconst gl = this.gl;\n\t\tif (this.fbo) gl.deleteFramebuffer(this.fbo);\n\t\tif (this.fboTexture) gl.deleteTexture(this.fboTexture);\n\n\t\tthis.fboTexture = gl.createTexture();\n\t\tgl.bindTexture(gl.TEXTURE_2D, this.fboTexture);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\twidth,\n\t\t\theight,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\tnull,\n\t\t);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n\t\tthis.fbo = gl.createFramebuffer();\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);\n\t\tgl.framebufferTexture2D(\n\t\t\tgl.FRAMEBUFFER,\n\t\t\tgl.COLOR_ATTACHMENT0,\n\t\t\tgl.TEXTURE_2D,\n\t\t\tthis.fboTexture,\n\t\t\t0,\n\t\t);\n\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t}\n\n\tprivate onRedraw(tickTime: number, delta: number) {\n\t\tconst latestMeshState = this.meshStates[this.meshStates.length - 1];\n\t\tlet canBeStatic = false;\n\n\t\t// 预计算常用值\n\t\tconst deltaFactor = delta / 500;\n\n\t\tif (latestMeshState) {\n\t\t\tlatestMeshState.mesh.bind();\n\t\t\t// 考虑到我们并不逐帧更新网格控制点,因此也不需要重复调用 updateMesh\n\t\t\tif (this.manualControl) latestMeshState.mesh.updateMesh();\n\n\t\t\tif (this.isNoCover) {\n\t\t\t\t// 批量处理alpha更新,减少循环开销\n\t\t\t\tlet hasActiveStates = false;\n\t\t\t\tfor (let i = this.meshStates.length - 1; i >= 0; i--) {\n\t\t\t\t\tconst state = this.meshStates[i];\n\t\t\t\t\t// 增加一个小的容错范围,避免浮点误差导致的过早删除\n\t\t\t\t\tif (state.alpha <= -0.1) {\n\t\t\t\t\t\t// 立即释放资源\n\t\t\t\t\t\tstate.mesh.dispose();\n\t\t\t\t\t\tstate.texture.dispose();\n\t\t\t\t\t\tthis.meshStates.splice(i, 1);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstate.alpha = Math.max(-0.1, state.alpha - deltaFactor);\n\t\t\t\t\t\thasActiveStates = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcanBeStatic = !hasActiveStates;\n\t\t\t} else {\n\t\t\t\t// 同样增加容错范围,允许稍微超过1以确保完全过渡完成\n\t\t\t\tif (latestMeshState.alpha >= 1.1) {\n\t\t\t\t\t// 批量清理旧状态\n\t\t\t\t\tconst deleted = this.meshStates.splice(0, this.meshStates.length - 1);\n\t\t\t\t\tfor (const state of deleted) {\n\t\t\t\t\t\tstate.mesh.dispose();\n\t\t\t\t\t\tstate.texture.dispose();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tlatestMeshState.alpha = Math.min(\n\t\t\t\t\t\t1.1,\n\t\t\t\t\t\tlatestMeshState.alpha + deltaFactor,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcanBeStatic =\n\t\t\t\t\tthis.meshStates.length === 1 && latestMeshState.alpha >= 1.1;\n\t\t\t}\n\t\t}\n\n\t\tconst gl = this.gl;\n\t\tthis.checkIfResize();\n\n\t\tif (!this.fbo) return canBeStatic;\n\n\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\tgl.clearColor(0, 0, 0, 0);\n\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\n\t\tconst lerpFactor = Math.min(1.0, delta / 100.0);\n\t\tthis.smoothedVolume += (this.volume - this.smoothedVolume) * lerpFactor;\n\n\t\t// 渲染所有网格状态\n\t\tfor (const state of this.meshStates) {\n\t\t\t// 1. 渲染到 FBO\n\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);\n\t\t\tgl.disable(gl.BLEND);\n\t\t\tgl.clearColor(0, 0, 0, 0);\n\t\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\n\t\t\tthis.mainProgram.use();\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tconst uTime = tickTime / 10000;\n\t\t\tthis.mainProgram.setUniform1f(\n\t\t\t\t\"u_aspect\",\n\t\t\t\tthis.manualControl ? 1 : this.canvas.width / this.canvas.height,\n\t\t\t);\n\t\t\tthis.mainProgram.setUniform1i(\"u_texture\", 0);\n\t\t\tthis.mainProgram.setUniform1f(\"u_volume\", this.volume);\n\t\t\tthis.mainProgram.setUniform1f(\"u_alpha\", 1.0);\n\t\t\tconst angle = (uTime + this.volume) * 2.0;\n\t\t\tthis.mainProgram.setUniform1f(\"u_sinAngle\", Math.sin(angle));\n\t\t\tthis.mainProgram.setUniform1f(\"u_cosAngle\", Math.cos(angle));\n\n\t\t\tstate.texture.bind();\n\t\t\tstate.mesh.bind();\n\t\t\tstate.mesh.draw();\n\n\t\t\t// 2. 渲染 FBO 到屏幕\n\t\t\tgl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\t\t\tgl.enable(gl.BLEND);\n\t\t\tgl.blendFuncSeparate(\n\t\t\t\tgl.SRC_ALPHA,\n\t\t\t\tgl.ONE_MINUS_SRC_ALPHA,\n\t\t\t\tgl.ONE,\n\t\t\t\tgl.ONE_MINUS_SRC_ALPHA,\n\t\t\t);\n\t\t\tthis.quadProgram.use();\n\t\t\tthis.quadProgram.setUniform1i(\"u_texture\", 0);\n\t\t\tthis.quadProgram.setUniform1f(\n\t\t\t\t\"u_alpha\",\n\t\t\t\teaseInOutSine(clamp01(state.alpha)),\n\t\t\t);\n\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, this.fboTexture);\n\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n\t\t\tconst a_pos = this.quadProgram.attrs.a_pos;\n\t\t\tgl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0);\n\t\t\tgl.enableVertexAttribArray(a_pos);\n\n\t\t\tgl.drawArrays(gl.TRIANGLES, 0, 6);\n\t\t\tgl.disableVertexAttribArray(a_pos);\n\t\t}\n\n\t\tgl.flush();\n\n\t\treturn canBeStatic;\n\t}\n\n\tprivate onTickBinded = this.onTick.bind(this);\n\n\tprivate requestTick() {\n\t\tif (this._disposed) return;\n\t\tif (this.tickHandle === 0)\n\t\t\tthis.tickHandle = requestAnimationFrame(this.onTickBinded);\n\t}\n\n\t// private supportTextureFloat = true;\n\n\tconstructor(canvas: HTMLCanvasElement) {\n\t\tsuper(canvas);\n\n\t\tconst gl = canvas.getContext(\"webgl\", { antialias: true });\n\t\tif (!gl) throw new Error(\"WebGL not supported\");\n\t\tif (!gl.getExtension(\"EXT_color_buffer_float\"))\n\t\t\tconsole.warn(\"EXT_color_buffer_float not supported\");\n\t\tif (!gl.getExtension(\"EXT_float_blend\")) {\n\t\t\tconsole.warn(\"EXT_float_blend not supported\");\n\t\t\t// this.supportTextureFloat = false;\n\t\t}\n\t\tif (!gl.getExtension(\"OES_texture_float_linear\"))\n\t\t\tconsole.warn(\"OES_texture_float_linear not supported\");\n\t\tif (!gl.getExtension(\"OES_texture_float\")) {\n\t\t\t// this.supportTextureFloat = false;\n\t\t\tconsole.warn(\"OES_texture_float not supported\");\n\t\t}\n\n\t\tthis.gl = gl;\n\t\tgl.enable(gl.BLEND);\n\t\tgl.blendFuncSeparate(\n\t\t\tgl.SRC_ALPHA,\n\t\t\tgl.ONE_MINUS_SRC_ALPHA,\n\t\t\tgl.ONE,\n\t\t\tgl.ONE_MINUS_SRC_ALPHA,\n\t\t);\n\t\tgl.enable(gl.DEPTH_TEST);\n\t\tgl.depthFunc(gl.ALWAYS);\n\n\t\tthis.mainProgram = new GLProgram(\n\t\t\tgl,\n\t\t\tmeshVertShader,\n\t\t\tmeshFragShader,\n\t\t\t\"main-program-mg\",\n\t\t);\n\n\t\tthis.quadProgram = new GLProgram(\n\t\t\tgl,\n\t\t\tquadVertShader,\n\t\t\tquadFragShader,\n\t\t\t\"quad-program\",\n\t\t);\n\t\tconst quadBuffer = gl.createBuffer();\n\t\tif (!quadBuffer) throw new Error(\"Failed to create quad buffer\");\n\t\tthis.quadBuffer = quadBuffer;\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n\t\tgl.bufferData(\n\t\t\tgl.ARRAY_BUFFER,\n\t\t\tnew Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]),\n\t\t\tgl.STATIC_DRAW,\n\t\t);\n\n\t\tthis.requestTick();\n\t}\n\n\tprotected override onResize(width: number, height: number): void {\n\t\tthis.targetSize.x = Math.ceil(width);\n\t\tthis.targetSize.y = Math.ceil(height);\n\t\tthis.requestTick();\n\t}\n\n\toverride setStaticMode(enable: boolean): void {\n\t\tthis.staticMode = enable;\n\t\tthis.lastFrameTime = performance.now();\n\t\tthis.requestTick();\n\t}\n\toverride setFPS(fps: number): void {\n\t\tthis.maxFPS = fps;\n\t}\n\toverride pause(): void {\n\t\tif (this.tickHandle) {\n\t\t\tcancelAnimationFrame(this.tickHandle);\n\t\t\tthis.tickHandle = 0;\n\t\t}\n\t\tthis.paused = true;\n\t}\n\toverride resume(): void {\n\t\tthis.paused = false;\n\t\tthis.requestTick();\n\t}\n\toverride async setAlbum(\n\t\talbumSource?: string | HTMLImageElement | HTMLVideoElement,\n\t\tisVideo?: boolean,\n\t): Promise<void> {\n\t\tif (\n\t\t\talbumSource === undefined ||\n\t\t\t(typeof albumSource === \"string\" && albumSource.trim().length === 0)\n\t\t) {\n\t\t\tthis.isNoCover = true;\n\t\t\treturn;\n\t\t}\n\t\tlet res: HTMLImageElement | HTMLVideoElement | null = null;\n\t\tlet blob: Blob | null = null;\n\t\tlet remainRetryTimes = 5;\n\t\twhile (!res && remainRetryTimes > 0) {\n\t\t\ttry {\n\t\t\t\tif (typeof albumSource === \"string\") {\n\t\t\t\t\tif (!isVideo && \"createImageBitmap\" in window) {\n\t\t\t\t\t\t// 如果支持 createImageBitmap 且是图片,直接 fetch blob\n\t\t\t\t\t\tconst response = await fetch(albumSource);\n\t\t\t\t\t\tblob = await response.blob();\n\t\t\t\t\t\t// 仍然需要一个 HTMLImageElement 来获取原始宽高(如果后续需要)\n\t\t\t\t\t\t// 但这里我们主要依赖 blob 来创建 bitmap\n\t\t\t\t\t\tres = await loadResourceFromUrl(URL.createObjectURL(blob), false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tres = await loadResourceFromUrl(albumSource, isVideo);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tres = await loadResourceFromElement(albumSource);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`failed on loading album resource, retrying (${remainRetryTimes})`,\n\t\t\t\t\t{\n\t\t\t\t\t\talbumSource,\n\t\t\t\t\t\terror,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tremainRetryTimes--;\n\t\t\t}\n\t\t}\n\t\tif (!res) {\n\t\t\tconsole.error(\"Failed to load album resource\", albumSource);\n\t\t\tthis.isNoCover = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.isNoCover = false;\n\t\t// resize image\n\t\tconst c = this.reduceImageSizeCanvas;\n\t\tconst ctx = c.getContext(\"2d\", {\n\t\t\twillReadFrequently: true,\n\t\t});\n\t\tif (!ctx) throw new Error(\"Failed to create canvas context\");\n\t\tctx.clearRect(0, 0, c.width, c.height);\n\t\t// Safari 不支持 filter\n\t\t// ctx.filter = baseFilter;\n\t\tconst imgw =\n\t\t\tres instanceof HTMLVideoElement ? res.videoWidth : res.naturalWidth;\n\t\tconst imgh =\n\t\t\tres instanceof HTMLVideoElement ? res.videoHeight : res.naturalHeight;\n\t\tif (imgw * imgh === 0) throw new Error(\"Invalid image size\");\n\n\t\tlet bitmap: ImageBitmap | null = null;\n\t\ttry {\n\t\t\tif (\"createImageBitmap\" in window) {\n\t\t\t\t// 避免在主线程进行同步解码,使用 fetch 获取 blob 后再创建 ImageBitmap\n\t\t\t\tif (blob) {\n\t\t\t\t\tbitmap = await createImageBitmap(blob, {\n\t\t\t\t\t\tresizeWidth: c.width,\n\t\t\t\t\t\tresizeHeight: c.height,\n\t\t\t\t\t\tresizeQuality: \"low\",\n\t\t\t\t\t});\n\t\t\t\t\tURL.revokeObjectURL(res.src); // 释放 object URL\n\t\t\t\t} else {\n\t\t\t\t\tbitmap = await createImageBitmap(res, {\n\t\t\t\t\t\tresizeWidth: c.width,\n\t\t\t\t\t\tresizeHeight: c.height,\n\t\t\t\t\t\tresizeQuality: \"low\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.warn(\"createImageBitmap failed\", e);\n\t\t}\n\n\t\tif (bitmap) {\n\t\t\tctx.drawImage(bitmap, 0, 0);\n\t\t\tbitmap.close();\n\t\t} else {\n\t\t\tctx.drawImage(res, 0, 0, imgw, imgh, 0, 0, c.width, c.height);\n\t\t}\n\n\t\tconst imageData = ctx.getImageData(0, 0, c.width, c.height);\n\n\t\t// 合并对比度、饱和度、亮度的处理,减少循环次数\n\t\tconst pixels = imageData.data;\n\t\tfor (let i = 0; i < pixels.length; i += 4) {\n\t\t\tlet r = pixels[i];\n\t\t\tlet g = pixels[i + 1];\n\t\t\tlet b = pixels[i + 2];\n\n\t\t\t// contrast 0.4\n\t\t\tr = (r - 128) * 0.4 + 128;\n\t\t\tg = (g - 128) * 0.4 + 128;\n\t\t\tb = (b - 128) * 0.4 + 128;\n\n\t\t\t// saturate 3.0\n\t\t\tconst gray = r * 0.3 + g * 0.59 + b * 0.11;\n\t\t\tr = gray * -2.0 + r * 3.0;\n\t\t\tg = gray * -2.0 + g * 3.0;\n\t\t\tb = gray * -2.0 + b * 3.0;\n\n\t\t\t// contrast 1.7\n\t\t\tr = (r - 128) * 1.7 + 128;\n\t\t\tg = (g - 128) * 1.7 + 128;\n\t\t\tb = (b - 128) * 1.7 + 128;\n\n\t\t\t// brightness 0.75\n\t\t\tpixels[i] = r * 0.75;\n\t\t\tpixels[i + 1] = g * 0.75;\n\t\t\tpixels[i + 2] = b * 0.75;\n\t\t}\n\n\t\tblurImage(imageData, 2, 4);\n\n\t\tif (this.manualControl && this.meshStates.length > 0) {\n\t\t\tthis.meshStates[0].texture.dispose();\n\t\t\tthis.meshStates[0].texture = new GLTexture(this.gl, imageData);\n\t\t} else {\n\t\t\tconst newMesh = new BHPMesh(\n\t\t\t\tthis.gl,\n\t\t\t\tthis.mainProgram.attrs.a_pos,\n\t\t\t\tthis.mainProgram.attrs.a_color,\n\t\t\t\tthis.mainProgram.attrs.a_uv,\n\t\t\t);\n\t\t\tnewMesh.resetSubdivition(50);\n\n\t\t\tconst chosenPreset =\n\t\t\t\tMath.random() > 0.8\n\t\t\t\t\t? generateControlPoints(6, 6)\n\t\t\t\t\t: CONTROL_POINT_PRESETS[\n\t\t\t\t\t\t\tMath.floor(Math.random() * CONTROL_POINT_PRESETS.length)\n\t\t\t\t\t\t];\n\n\t\t\tnewMesh.resizeControlPoints(chosenPreset.width, chosenPreset.height);\n\t\t\tconst uPower = 2 / (chosenPreset.width - 1);\n\t\t\tconst vPower = 2 / (chosenPreset.height - 1);\n\t\t\tfor (const cp of chosenPreset.conf) {\n\t\t\t\tconst p = newMesh.getControlPoint(cp.cx, cp.cy);\n\t\t\t\tp.location.x = cp.x;\n\t\t\t\tp.location.y = cp.y;\n\t\t\t\tp.uRot = (cp.ur * Math.PI) / 180;\n\t\t\t\tp.vRot = (cp.vr * Math.PI) / 180;\n\t\t\t\tp.uScale = uPower * cp.up;\n\t\t\t\tp.vScale = vPower * cp.vp;\n\t\t\t}\n\n\t\t\tnewMesh.updateMesh();\n\t\t\t// this.currentImageData = imageData;\n\n\t\t\tconst albumTexture = new GLTexture(this.gl, imageData);\n\t\t\tconst newState: MeshState = {\n\t\t\t\tmesh: newMesh,\n\t\t\t\ttexture: albumTexture,\n\t\t\t\talpha: 0,\n\t\t\t};\n\t\t\tthis.meshStates.push(newState);\n\t\t}\n\n\t\tthis.requestTick();\n\t}\n\toverride setLowFreqVolume(volume: number): void {\n\t\tthis.volume = volume / 10;\n\t}\n\toverride setHasLyric(_hasLyric: boolean): void {\n\t\t// 不再考虑实现\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tif (this.tickHandle) {\n\t\t\tcancelAnimationFrame(this.tickHandle);\n\t\t\tthis.tickHandle = 0;\n\t\t}\n\t\tthis._disposed = true;\n\t\tthis.mainProgram.dispose();\n\t\tthis.quadProgram.dispose();\n\t\tthis.gl.deleteBuffer(this.quadBuffer);\n\t\tif (this.fbo) this.gl.deleteFramebuffer(this.fbo);\n\t\tif (this.fboTexture) this.gl.deleteTexture(this.fboTexture);\n\t\tfor (const state of this.meshStates) {\n\t\t\tstate.mesh.dispose();\n\t\t\tstate.texture.dispose();\n\t\t}\n\t}\n\n\tenablePerformanceMonitor(enable: boolean): void {\n\t\tthis.enablePerformanceMonitoring = enable;\n\t\tif (enable) {\n\t\t\tthis.frameCount = 0;\n\t\t\tthis.lastFPSUpdate = performance.now();\n\t\t}\n\t}\n\n\tgetCurrentFPS(): number {\n\t\treturn this.currentFPS;\n\t}\n\n\tprivate updatePerformanceStats(tickTime: number) {\n\t\tif (!this.enablePerformanceMonitoring) return;\n\n\t\tthis.frameCount++;\n\t\tif (tickTime - this.lastFPSUpdate > 1000) {\n\t\t\tthis.currentFPS = this.frameCount;\n\t\t\tthis.frameCount = 0;\n\t\t\tthis.lastFPSUpdate = tickTime;\n\t\t}\n\t}\n}\n","import { Application } from \"@pixi/app\";\nimport { Texture } from \"@pixi/core\";\nimport { Container } from \"@pixi/display\";\nimport { BlurFilter } from \"@pixi/filter-blur\";\nimport { BulgePinchFilter } from \"@pixi/filter-bulge-pinch\";\nimport { ColorMatrixFilter } from \"@pixi/filter-color-matrix\";\nimport { Sprite } from \"@pixi/sprite\";\nimport {\n\tloadResourceFromElement,\n\tloadResourceFromUrl,\n} from \"../utils/resource\";\nimport { BaseRenderer } from \"./base\";\nimport { clampPositive } from \"#utils/clamp.ts\";\n\nclass TimedContainer extends Container {\n\tpublic time = 0;\n}\n\nexport class PixiRenderer extends BaseRenderer {\n\tprivate app: Application;\n\tprivate curContainer?: TimedContainer;\n\tprivate staticMode = false;\n\tprivate lastContainer: Set<TimedContainer> = new Set();\n\tprivate onTick = (delta: number): void => {\n\t\tfor (const lastContainer of this.lastContainer) {\n\t\t\tlastContainer.alpha = clampPositive(lastContainer.alpha - delta / 60);\n\t\t\tif (lastContainer.alpha <= 0) {\n\t\t\t\tthis.app.stage.removeChild(lastContainer);\n\t\t\t\tthis.lastContainer.delete(lastContainer);\n\t\t\t\tlastContainer.destroy(true);\n\t\t\t}\n\t\t}\n\n\t\tif (this.curContainer) {\n\t\t\tthis.curContainer.alpha = Math.min(\n\t\t\t\t1,\n\t\t\t\tthis.curContainer.alpha + delta / 60,\n\t\t\t);\n\t\t\tconst [s1, s2, s3, s4] = this.curContainer.children as Sprite[];\n\t\t\tconst maxSize = Math.max(this.app.screen.width, this.app.screen.height);\n\t\t\ts1.position.set(this.app.screen.width / 2, this.app.screen.height / 2);\n\t\t\ts2.position.set(\n\t\t\t\tthis.app.screen.width / 2.5,\n\t\t\t\tthis.app.screen.height / 2.5,\n\t\t\t);\n\t\t\ts3.position.set(this.app.screen.width / 2, this.app.screen.height / 2);\n\t\t\ts4.position.set(this.app.screen.width / 2, this.app.screen.height / 2);\n\t\t\ts1.width = maxSize * Math.sqrt(2);\n\t\t\ts1.height = s1.width;\n\t\t\ts2.width = maxSize * 0.8;\n\t\t\ts2.height = s2.width;\n\t\t\ts3.width = maxSize * 0.5;\n\t\t\ts3.height = s3.width;\n\t\t\ts4.width = maxSize * 0.25;\n\t\t\ts4.height = s4.width;\n\n\t\t\tthis.curContainer.time += delta * this.flowSpeed;\n\n\t\t\ts1.rotation += (delta / 1000) * this.flowSpeed;\n\t\t\ts2.rotation -= (delta / 500) * this.flowSpeed;\n\t\t\ts3.rotation += (delta / 1000) * this.flowSpeed;\n\t\t\ts4.rotation -= (delta / 750) * this.flowSpeed;\n\n\t\t\ts3.x =\n\t\t\t\tthis.app.screen.width / 2 +\n\t\t\t\t(this.app.screen.width / 4) *\n\t\t\t\t\tMath.cos((this.curContainer.time / 1000) * 0.75);\n\t\t\ts3.y =\n\t\t\t\tthis.app.screen.height / 2 +\n\t\t\t\t(this.app.screen.width / 4) *\n\t\t\t\t\tMath.cos((this.curContainer.time / 1000) * 0.75);\n\n\t\t\ts4.x =\n\t\t\t\tthis.app.screen.width / 2 +\n\t\t\t\t(this.app.screen.width / 4) * 0.1 +\n\t\t\t\tMath.cos(this.curContainer.time * 0.006 * 0.75);\n\t\t\ts4.y =\n\t\t\t\tthis.app.screen.height / 2 +\n\t\t\t\t(this.app.screen.width / 4) * 0.1 +\n\t\t\t\tMath.cos(this.curContainer.time * 0.006 * 0.75);\n\n\t\t\tif (\n\t\t\t\tthis.curContainer.alpha >= 1 &&\n\t\t\t\tthis.lastContainer.size === 0 &&\n\t\t\t\tthis.staticMode\n\t\t\t) {\n\t\t\t\tthis.app.ticker.stop();\n\t\t\t}\n\t\t}\n\t};\n\tconstructor(protected override canvas: HTMLCanvasElement) {\n\t\tsuper(canvas);\n\t\tthis.app = new Application({\n\t\t\tview: canvas,\n\t\t\tresizeTo: this.canvas,\n\t\t\tpowerPreference: \"low-power\",\n\t\t\tbackgroundAlpha: 1,\n\t\t});\n\t\tthis.rebuildFilters();\n\t\tthis.app.ticker.maxFPS = 30;\n\t\tthis.app.ticker.add(this.onTick);\n\t\tthis.app.ticker.start();\n\t}\n\n\tprotected override onResize(width: number, height: number): void {\n\t\tsuper.onResize(width, height);\n\t\tthis.app.resize();\n\t\tthis.rebuildFilters();\n\t}\n\n\toverride setRenderScale(scale: number): void {\n\t\tsuper.setRenderScale(scale);\n\t\tthis.rebuildFilters();\n\t}\n\tprivate rebuildFilters() {\n\t\tconst minBorder = Math.min(this.canvas.width, this.canvas.height);\n\t\tconst maxBorder = Math.max(this.canvas.width, this.canvas.height);\n\t\tconst c0 = new ColorMatrixFilter();\n\t\tc0.saturate(1.2, false);\n\t\tconst c1 = new ColorMatrixFilter();\n\t\tc1.brightness(0.6, false);\n\t\tconst c2 = new ColorMatrixFilter();\n\t\tc2.contrast(0.3, true);\n\t\tfor (const filter of this.app.stage.filters ?? []) {\n\t\t\tfilter.destroy();\n\t\t}\n\t\tthis.app.stage.filters = [];\n\t\tthis.app.stage.filters.push(new BlurFilter(5, 1));\n\t\tthis.app.stage.filters.push(new BlurFilter(10, 1));\n\t\tthis.app.stage.filters.push(new BlurFilter(20, 2));\n\t\tthis.app.stage.filters.push(new BlurFilter(40, 2));\n\t\tthis.app.stage.filters.push(new BlurFilter(80, 2));\n\t\tif (minBorder > 768) this.app.stage.filters.push(new BlurFilter(160, 4));\n\t\tif (minBorder > 768 * 2)\n\t\t\tthis.app.stage.filters.push(new BlurFilter(320, 4));\n\n\t\tthis.app.stage.filters.push(c0, c1, c2);\n\t\tthis.app.stage.filters.push(new BlurFilter(5, 1));\n\t\tif (Math.random() > 0.5) {\n\t\t\tthis.app.stage.filters.push(\n\t\t\t\tnew BulgePinchFilter({\n\t\t\t\t\tradius: (maxBorder + minBorder) / 2,\n\t\t\t\t\tstrength: 1,\n\t\t\t\t\tcenter: [0.25, 1],\n\t\t\t\t}),\n\t\t\t);\n\t\t\tthis.app.stage.filters.push(\n\t\t\t\tnew BulgePinchFilter({\n\t\t\t\t\tradius: (maxBorder + minBorder) / 2,\n\t\t\t\t\tstrength: 1,\n\t\t\t\t\tcenter: [0.75, 0],\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tthis.app.stage.filters.push(\n\t\t\t\tnew BulgePinchFilter({\n\t\t\t\t\tradius: (maxBorder + minBorder) / 2,\n\t\t\t\t\tstrength: 1,\n\t\t\t\t\tcenter: [0.75, 1],\n\t\t\t\t}),\n\t\t\t);\n\t\t\tthis.app.stage.filters.push(\n\t\t\t\tnew BulgePinchFilter({\n\t\t\t\t\tradius: (maxBorder + minBorder) / 2,\n\t\t\t\t\tstrength: 1,\n\t\t\t\t\tcenter: [0.25, 0],\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\toverride setStaticMode(enable = false): void {\n\t\tthis.staticMode = enable;\n\t\tthis.app.ticker.start();\n\t}\n\n\toverride setFPS(fps: number): void {\n\t\tthis.app.ticker.maxFPS = fps;\n\t}\n\n\toverride pause(): void {\n\t\tthis.app.ticker.stop();\n\t\tthis.app.render();\n\t}\n\n\toverride resume(): void {\n\t\tthis.app.ticker.start();\n\t}\n\n\toverride setLowFreqVolume(_volume: number): void {\n\t\t// NOOP\n\t}\n\n\toverride setHasLyric(_hasLyric: boolean): void {\n\t\t// NOOP\n\t}\n\n\toverride async setAlbum(\n\t\talbumSource?: string | HTMLImageElement | HTMLVideoElement,\n\t\tisVideo?: boolean,\n\t): Promise<void> {\n\t\tif (\n\t\t\t!albumSource ||\n\t\t\t(typeof albumSource === \"string\" && albumSource.trim().length === 0)\n\t\t)\n\t\t\treturn;\n\t\tlet res: HTMLImageElement | HTMLVideoElement | null = null;\n\t\tlet remainRetryTimes = 5;\n\t\tlet tex: Texture | null = null;\n\t\twhile (!tex?.baseTexture?.resource?.valid && remainRetryTimes > 0) {\n\t\t\ttry {\n\t\t\t\tif (typeof albumSource === \"string\") {\n\t\t\t\t\tres = await loadResourceFromUrl(albumSource, isVideo);\n\t\t\t\t} else {\n\t\t\t\t\tres = await loadResourceFromElement(albumSource);\n\t\t\t\t}\n\t\t\t\ttex = Texture.from(res, {\n\t\t\t\t\tresourceOptions: {\n\t\t\t\t\t\tautoLoad: false,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tawait tex.baseTexture.resource.load();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`failed on loading album image, retrying (${remainRetryTimes})`,\n\t\t\t\t\talbumSource,\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\ttex = null;\n\t\t\t\tremainRetryTimes--;\n\t\t\t}\n\t\t}\n\t\tif (!tex) return;\n\t\tconst container = new TimedContainer();\n\t\tconst s1 = new Sprite(tex);\n\t\tconst s2 = new Sprite(tex);\n\t\tconst s3 = new Sprite(tex);\n\t\tconst s4 = new Sprite(tex);\n\t\ts1.anchor.set(0.5, 0.5);\n\t\ts2.anchor.set(0.5, 0.5);\n\t\ts3.anchor.set(0.5, 0.5);\n\t\ts4.anchor.set(0.5, 0.5);\n\t\ts1.rotation = Math.random() * Math.PI * 2;\n\t\ts2.rotation = Math.random() * Math.PI * 2;\n\t\ts3.rotation = Math.random() * Math.PI * 2;\n\t\ts4.rotation = Math.random() * Math.PI * 2;\n\t\tcontainer.addChild(s1, s2, s3, s4);\n\t\tif (this.curContainer) this.lastContainer.add(this.curContainer);\n\t\tthis.curContainer = container;\n\t\tthis.app.stage.addChild(container);\n\t\tthis.curContainer.alpha = 0;\n\t\tthis.app.ticker.start();\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tthis.app.ticker.remove(this.onTick);\n\t\tthis.app.destroy(true);\n\t}\n\n\toverride getElement(): HTMLElement {\n\t\treturn this.canvas;\n\t}\n}\n","/**\n * @fileoverview\n * 一个播放歌词的组件\n * @author SteveXMH\n */\n\nexport { AbstractBaseRenderer, BaseRenderer } from \"./base.ts\";\nexport { MeshGradientRenderer } from \"./mesh-renderer/index.ts\";\nexport { PixiRenderer } from \"./pixi-renderer.ts\";\nimport type { AbstractBaseRenderer, BaseRenderer } from \"./base.ts\";\n\nexport class BackgroundRender<Renderer extends BaseRenderer>\n\timplements AbstractBaseRenderer\n{\n\tprivate element: HTMLCanvasElement;\n\tprivate renderer: Renderer;\n\tconstructor(renderer: Renderer, canvas: HTMLCanvasElement) {\n\t\tthis.renderer = renderer;\n\n\t\tthis.element = canvas;\n\t\tcanvas.style.pointerEvents = \"none\";\n\t\tcanvas.style.zIndex = \"-1\";\n\t\tcanvas.style.contain = \"strict\";\n\t}\n\n\tstatic new<Renderer extends BaseRenderer>(type: {\n\t\tnew (canvas: HTMLCanvasElement): Renderer;\n\t}): BackgroundRender<Renderer> {\n\t\tconst newCanvas = document.createElement(\"canvas\");\n\t\treturn new BackgroundRender(new type(newCanvas), newCanvas);\n\t}\n\n\tsetRenderScale(scale: number): void {\n\t\tthis.renderer.setRenderScale(scale);\n\t}\n\n\tsetFlowSpeed(speed: number): void {\n\t\tthis.renderer.setFlowSpeed(speed);\n\t}\n\tsetStaticMode(enable: boolean): void {\n\t\tthis.renderer.setStaticMode(enable);\n\t}\n\tsetFPS(fps: number): void {\n\t\tthis.renderer.setFPS(fps);\n\t}\n\tpause(): void {\n\t\tthis.renderer.pause();\n\t}\n\tresume(): void {\n\t\tthis.renderer.resume();\n\t}\n\tsetLowFreqVolume(volume: number): void {\n\t\tthis.renderer.setLowFreqVolume(volume);\n\t}\n\tsetHasLyric(hasLyric: boolean): void {\n\t\tthis.renderer.setHasLyric(hasLyric);\n\t}\n\tsetAlbum(\n\t\talbumSource: string | HTMLImageElement | HTMLVideoElement,\n\t\tisVideo?: boolean,\n\t): Promise<void> {\n\t\treturn this.renderer.setAlbum(albumSource, isVideo);\n\t}\n\tgetElement(): HTMLCanvasElement {\n\t\treturn this.element;\n\t}\n\tdispose(): void {\n\t\tthis.renderer.dispose();\n\t\tthis.element.remove();\n\t}\n}\n",".lyricLineWrapper {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: flex-start;\n\twidth: 100%;\n\tbox-sizing: border-box;\n\tpadding: 0.4em var(--lyric-line-padding-x);\n\tborder-radius: 0.25em;\n\n\tgap: 0.3em;\n\n\twill-change: transform, opacity, filter;\n\ttransition:\n\t\topacity 0.4s ease,\n\t\tfilter 0.4s ease,\n\t\tbackground-color 0.25s ease;\n\n\t&:hover {\n\t\tbackground-color: var(--amll-lp-hover-bg-color, #fff1);\n\t}\n\n\t&:active {\n\t\tbackground-color: var(--amll-lp-hover-bg-color, #ffffff05);\n\t}\n}\n\n.lyricLine {\n\tposition: relative;\n\tbox-sizing: border-box;\n\twidth: var(--amll-lp-width, 100%);\n\tmin-width: var(--amll-lp-width, 100%);\n\tmax-width: var(--amll-lp-width, 100%);\n\theight: fit-content;\n\n\tpadding: 0.2em;\n\tmargin: -0.2em;\n\n\tcontain: layout style paint;\n\tcontent-visibility: auto;\n\tcontain-intrinsic-size: auto 40px;\n\tbackface-visibility: hidden;\n\ttransform-origin: left;\n\twill-change: transform, filter, opacity;\n\n\ttransition: box-shadow 0.25s;\n}\n\n.lyricDuetLine {\n\ttext-align: right;\n\ttransform-origin: right;\n}\n\n.lyricMainLine {\n\tmargin: -1em;\n\tpadding: 1em;\n\ttransition: opacity 0.3s 0.1s;\n\tcontain: layout style;\n\n\t& span {\n\t\tdisplay: inline-block;\n\t\ttext-align: start;\n\t\tvertical-align: bottom;\n\t}\n\n\t.romanWord {\n\t\tdisplay: flex;\n\t\tpadding-inline-end: 0.3em;\n\t\tfont-size: 0.5em;\n\t\tline-height: 1em;\n\t}\n\n\t.rubyWord {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\tmin-height: 1em;\n\t\tfont-size: 0.5em;\n\t\tline-height: 1em;\n\t}\n\n\t.wordWithRuby {\n\t\tdisplay: inline-flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t\tvertical-align: bottom;\n\t}\n\n\t.wordBody {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: center;\n\t}\n\n\t& > span,\n\tspan.emphasizeWrapper {\n\t\tdisplay: inline-block;\n\t\tmargin: -1em;\n\t\tpadding: 1em;\n\t\twhite-space: pre-wrap;\n\t\tvertical-align: bottom;\n\t\twill-change: transform, text-shadow;\n\t\tcontain: layout style;\n\n\t\t&.emphasize,\n\t\tspan.emphasize {\n\t\t\tmargin: -1em;\n\t\t\tpadding: 1em;\n\t\t\tbackface-visibility: hidden;\n\n\t\t\t& > span {\n\t\t\t\tmargin: -1em;\n\t\t\t\tpadding: 1em;\n\t\t\t\twill-change: transform, text-shadow;\n\t\t\t\tbackface-visibility: hidden;\n\t\t\t}\n\t\t}\n\t}\n}\n\n.lyricBgLine {\n\topacity: 0.4;\n\tfont-size: max(calc(1em * var(--amll-lp-bg-line-scale, 0.7)), 10px);\n\ttransition:\n\t\tbackground-color 0.25s,\n\t\tbox-shadow 0.25s;\n\n\t.lyricMainLine {\n\t\tpadding: 1.2em 1em;\n\t}\n\n\t&.active {\n\t\topacity: 0.4;\n\t\ttransition:\n\t\t\tbackground-color 0.25s,\n\t\t\tbox-shadow 0.25s;\n\t}\n}\n\n.lyricSubLine {\n\topacity: 0.3;\n\tfont-size: max(0.5em, 10px);\n\tline-height: 1.5em;\n\ttransition: opacity 0.2s 0.25s;\n\n\t@supports (mix-blend-mode: plus-lighter) {\n\t\topacity: 0.3;\n\t}\n}\n\n.bottomLine {\n\tpadding-top: 0;\n\tpadding-bottom: 0;\n\tline-height: 1.8em;\n\tcursor: default;\n\n\t&:empty {\n\t\tdisplay: none;\n\t\theight: 0;\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t}\n}\n\n.bgWrapper {\n\tposition: absolute;\n\ttop: 100%;\n\tleft: var(--lyric-line-padding-x);\n\tz-index: -1;\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: inherit;\n\twidth: calc(100% - var(--lyric-line-padding-x) * 2);\n\n\tvisibility: visible;\n\tpointer-events: auto;\n\topacity: 0;\n\ttransform-origin: left top;\n\ttransition: opacity 0.3s ease;\n}\n\n.bgWrapperTop {\n\tposition: relative;\n\tleft: 0;\n\twidth: 100%;\n\ttop: auto;\n\tbottom: auto;\n\tmargin-top: -999px;\n\ttransform-origin: left bottom;\n}\n\n.bgWrapperActive {\n\tposition: relative;\n\tleft: 0;\n\twidth: 100%;\n\ttop: auto;\n\tbottom: auto;\n\topacity: 1;\n}\n\n.bgWrapperHidden {\n\tvisibility: hidden;\n\tpointer-events: none;\n}\n\n.interludeDots {\n\tposition: absolute;\n\tleft: 0;\n\tdisplay: flex;\n\tgap: 0.25em;\n\twidth: fit-content;\n\theight: clamp(0.5em, 1vh, 3em);\n\tpadding: 2.5% 0.75em;\n\n\topacity: 0;\n\ttransform-origin: center;\n\ttransition: opacity 0.25s;\n\n\t&.enabled {\n\t\topacity: 1;\n\t}\n\n\t& > * {\n\t\tdisplay: inline-block;\n\t\twidth: clamp(0.5em, 1vh, 3em);\n\t\theight: clamp(0.5em, 1vh, 3em);\n\t\tmargin-right: 4px;\n\t\tborder-radius: 50%;\n\t\tbackground-color: var(--amll-lp-color, white);\n\t\taspect-ratio: 1 / 1;\n\t}\n\n\t&.duet {\n\t\tright: 0;\n\t\ttransform-origin: center;\n\t}\n}\n\n.disableSpring > *,\n.disableSpring .lyricLine {\n\ttransition:\n\t\tfilter 0.25s,\n\t\ttransform 0.5s,\n\t\tbackground-color 0.25s,\n\t\tbox-shadow 0.25s;\n}\n\n.tmpDisableTransition {\n\t/* biome-ignore lint/complexity/noImportantStyles: 覆盖内联样式 */\n\ttransition: none !important;\n}\n\n:global(.amll-lyric-player) {\n\t--lyric-line-padding-x: 1em;\n\n\t@media screen and (max-width: 500px) {\n\t\t--lyric-line-padding-x: 20px;\n\t}\n\n\t&:hover .lyricLine,\n\t&:hover .lyricLineWrapper {\n\t\t/* biome-ignore lint/complexity/noImportantStyles: 覆盖内联样式 */\n\t\tfilter: unset !important;\n\t}\n\n\t&:not(.playing) .bgWrapper {\n\t\tposition: relative;\n\t\ttop: auto;\n\t\tbottom: auto;\n\t\topacity: 1;\n\t\tleft: 0;\n\t\twidth: 100%;\n\t}\n\n\t&.hasDuetLine {\n\t\t.lyricLine:not(.lyricDuetLine) {\n\t\t\tpadding-right: 15%;\n\t\t}\n\n\t\t.lyricDuetLine {\n\t\t\tpadding-left: 15%;\n\t\t}\n\n\t\t.lyricLineWrapper:has(.lyricDuetLine) {\n\t\t\talign-items: flex-end;\n\n\t\t\t.bgWrapper {\n\t\t\t\ttransform-origin: right top;\n\t\t\t}\n\n\t\t\t.bgWrapperTop {\n\t\t\t\ttransform-origin: right bottom;\n\t\t\t}\n\t\t}\n\t}\n}\n","import type { LyricLine, OptimizeLyricOptions } from \"../interfaces.ts\";\n\nconst DEFAULT_OPTIMIZE_OPTIONS: OptimizeLyricOptions = {\n\tnormalizeSpaces: true,\n\tresetLineTimestamps: true,\n\tconvertExcessiveBackgroundLines: true,\n\tsyncMainAndBackgroundLines: true,\n\tcleanUnintentionalOverlaps: true,\n\ttryAdvanceStartTime: true,\n};\n\n/**\n * 规范化歌词中的空格,将多个连续空格替换为一个空格\n */\nfunction normalizeSpaces(lines: LyricLine[]) {\n\tfor (const line of lines) {\n\t\tfor (const word of line.words) {\n\t\t\tword.word = word.word.replace(/\\s+/g, \" \");\n\t\t}\n\t}\n}\n\n/**\n * 将行级时间戳强行设为字级时间戳\n */\nfunction resetLineTimestamps(lines: LyricLine[]) {\n\tfor (const line of lines) {\n\t\t// 主要是给 TTML 解析器打补丁,其解析逐行歌词时获得的词时间戳均为0\n\t\t// 如果只有一个词,且该词的起止时间均为0,且行时间戳不全为0,则将行时间戳同步给词时间戳\n\t\tif (\n\t\t\tline.words.length === 1 &&\n\t\t\tline.words[0].startTime === 0 &&\n\t\t\tline.words[0].endTime === 0 &&\n\t\t\t(line.startTime !== 0 || line.endTime !== 0)\n\t\t) {\n\t\t\tline.words[0].startTime = line.startTime;\n\t\t\tline.words[0].endTime = line.endTime;\n\t\t} else if (line.words.length > 0) {\n\t\t\tconst firstWord = line.words[0];\n\t\t\tconst lastWord = line.words[line.words.length - 1];\n\n\t\t\tline.startTime = firstWord.startTime;\n\t\t\tline.endTime = lastWord.endTime;\n\t\t}\n\t}\n}\n\n/**\n * 把多行背景人声转换为单行背景人声 + 主歌词行的形式\n */\nfunction convertExcessiveBackgroundLines(lines: LyricLine[]) {\n\tlet consecutiveBgCount = 0;\n\n\tfor (const line of lines) {\n\t\tif (line.isBG) {\n\t\t\tconsecutiveBgCount++;\n\t\t\tif (consecutiveBgCount > 1) {\n\t\t\t\tline.isBG = false;\n\t\t\t}\n\t\t} else {\n\t\t\tconsecutiveBgCount = 0;\n\t\t}\n\t}\n}\n\n/**\n * 同步主歌词与背景人声的时间\n *\n * 取两者中最早的开始时间和最晚的结束时间,应用给双方\n */\nfunction syncMainAndBackgroundLines(lines: LyricLine[]) {\n\tfor (let i = lines.length - 1; i >= 0; i--) {\n\t\tconst line = lines[i];\n\t\tif (line.isBG) continue;\n\n\t\tconst nextLine = lines[i + 1];\n\t\tif (nextLine?.isBG) {\n\t\t\tconst allWords = [...line.words, ...nextLine.words].filter(\n\t\t\t\t(w) => w.word.trim().length > 0,\n\t\t\t);\n\n\t\t\tif (allWords.length > 0) {\n\t\t\t\tconst minStart = Math.min(...allWords.map((w) => w.startTime));\n\t\t\t\tconst maxEnd = Math.max(...allWords.map((w) => w.endTime));\n\n\t\t\t\tconst finalStart = Math.min(\n\t\t\t\t\tminStart,\n\t\t\t\t\tline.startTime,\n\t\t\t\t\tnextLine.startTime,\n\t\t\t\t);\n\t\t\t\tconst finalEnd = Math.max(maxEnd, line.endTime, nextLine.endTime);\n\n\t\t\t\tline.startTime = finalStart;\n\t\t\t\tline.endTime = finalEnd;\n\t\t\t\tnextLine.startTime = finalStart;\n\t\t\t\tnextLine.endTime = finalEnd;\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * 清洗非刻意的重叠\n *\n * 如果重叠大于100ms 且 重叠超过下一行时长的10%,则视为刻意重叠,否则将结束时间设为下一行的开始时间\n */\nfunction cleanUnintentionalOverlaps(lines: LyricLine[]) {\n\tfor (let i = 0; i < lines.length - 1; i++) {\n\t\tconst line = lines[i];\n\t\tif (line.isBG) continue;\n\n\t\tlet nextMainIndex = i + 1;\n\t\twhile (nextMainIndex < lines.length && lines[nextMainIndex].isBG) {\n\t\t\tnextMainIndex++;\n\t\t}\n\n\t\tif (nextMainIndex < lines.length) {\n\t\t\tconst nextLine = lines[nextMainIndex];\n\t\t\tconst overlap = line.endTime - nextLine.startTime;\n\n\t\t\tif (overlap > 0) {\n\t\t\t\tconst nextDuration = nextLine.endTime - nextLine.startTime;\n\t\t\t\tconst percentageThreshold = nextDuration * 0.1;\n\n\t\t\t\t// 重叠大于100ms 且 重叠超过下一行时长的10%\n\t\t\t\tconst isIntentionalOverlap =\n\t\t\t\t\toverlap > 100 && overlap > percentageThreshold;\n\n\t\t\t\tif (!isIntentionalOverlap) {\n\t\t\t\t\tline.endTime = nextLine.startTime;\n\n\t\t\t\t\tconst attachedBgLine = lines[i + 1];\n\t\t\t\t\tif (attachedBgLine?.isBG) {\n\t\t\t\t\t\tattachedBgLine.endTime = nextLine.startTime;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * 尝试让歌词提前最多 600ms 开始,如果有重叠则尝试最多提前 400ms 或上一行时长的 30%\n */\nfunction tryAdvanceStartTime(lines: LyricLine[]) {\n\tconst defaultAdvanceAmount = 600;\n\tconst fallbackAdvanceAmount = 400;\n\tconst fallbackAdvanceRatio = 0.3;\n\n\tlet prevLineStartTime = 0;\n\tlet prevLineEndTime = 0;\n\tlet prevMainGroupStartTime = 0;\n\tlet prevMainGroupEndTime = 0;\n\tlet hasPrevLine = false;\n\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i];\n\t\tif (line.isBG) continue;\n\n\t\tconst originalStartTime = line.startTime;\n\t\tconst originalEndTime = line.endTime;\n\n\t\tlet targetAdvanceAmount = 0;\n\t\tlet safeBoundary = 0;\n\n\t\tif (hasPrevLine) {\n\t\t\tconst originallyHadGap = originalStartTime >= prevLineEndTime;\n\n\t\t\tif (originallyHadGap) {\n\t\t\t\ttargetAdvanceAmount = defaultAdvanceAmount;\n\t\t\t\tsafeBoundary = prevMainGroupEndTime;\n\t\t\t} else {\n\t\t\t\ttargetAdvanceAmount = fallbackAdvanceAmount;\n\t\t\t\tconst prevDuration = prevLineEndTime - prevLineStartTime;\n\t\t\t\tsafeBoundary = prevLineStartTime + prevDuration * fallbackAdvanceRatio;\n\t\t\t}\n\t\t} else {\n\t\t\ttargetAdvanceAmount = defaultAdvanceAmount;\n\t\t\tsafeBoundary = 0;\n\t\t}\n\n\t\tconst targetTime = line.startTime - targetAdvanceAmount;\n\t\tconst newStartTime = Math.max(safeBoundary, targetTime);\n\n\t\tif (newStartTime < line.startTime) {\n\t\t\tline.startTime = newStartTime;\n\t\t}\n\n\t\tconst nextLine = lines[i + 1];\n\t\tif (nextLine?.isBG) {\n\t\t\tnextLine.startTime = line.startTime;\n\t\t}\n\n\t\tif (hasPrevLine) {\n\t\t\tconst overlapsPrevGroup =\n\t\t\t\toriginalStartTime < prevMainGroupEndTime &&\n\t\t\t\toriginalEndTime > prevMainGroupStartTime;\n\n\t\t\tif (overlapsPrevGroup) {\n\t\t\t\tprevMainGroupStartTime = Math.min(\n\t\t\t\t\tprevMainGroupStartTime,\n\t\t\t\t\toriginalStartTime,\n\t\t\t\t);\n\t\t\t\tprevMainGroupEndTime = Math.max(prevMainGroupEndTime, originalEndTime);\n\t\t\t} else {\n\t\t\t\tprevMainGroupStartTime = originalStartTime;\n\t\t\t\tprevMainGroupEndTime = originalEndTime;\n\t\t\t}\n\t\t} else {\n\t\t\tprevMainGroupStartTime = originalStartTime;\n\t\t\tprevMainGroupEndTime = originalEndTime;\n\t\t}\n\n\t\tprevLineStartTime = originalStartTime;\n\t\tprevLineEndTime = originalEndTime;\n\t\thasPrevLine = true;\n\t}\n}\n\n/**\n * 优化歌词行的展示效果\n *\n * 注意会直接原地修改入参,确保你已经提前深克隆了歌词行数组\n * @param lines 歌词行数组\n * @param options 优化的可选配置,默认全部开启\n */\nexport function optimizeLyricLines(\n\tlines: LyricLine[],\n\toptions?: OptimizeLyricOptions,\n): void {\n\tconst config = { ...DEFAULT_OPTIMIZE_OPTIONS, ...options };\n\n\tif (config.normalizeSpaces) {\n\t\tnormalizeSpaces(lines);\n\t}\n\tif (config.resetLineTimestamps) {\n\t\tresetLineTimestamps(lines);\n\t}\n\tif (config.convertExcessiveBackgroundLines) {\n\t\tconvertExcessiveBackgroundLines(lines);\n\t}\n\tif (config.syncMainAndBackgroundLines) {\n\t\tsyncMainAndBackgroundLines(lines);\n\t}\n\tif (config.cleanUnintentionalOverlaps) {\n\t\tcleanUnintentionalOverlaps(lines);\n\t}\n\tif (config.tryAdvanceStartTime) {\n\t\ttryAdvanceStartTime(lines);\n\t}\n}\n","import type { Disposable, HasElement } from \"#interfaces\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { clamp, clamp01, clampPositive } from \"#utils/clamp.ts\";\n\nfunction easeInOutBack(x: number): number {\n\tconst c1 = 1.70158;\n\tconst c2 = c1 * 1.525;\n\n\treturn x < 0.5\n\t\t? ((2 * x) ** 2 * ((c2 + 1) * 2 * x - c2)) / 2\n\t\t: ((2 * x - 2) ** 2 * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2;\n}\n\nfunction easeOutExpo(x: number): number {\n\treturn x === 1 ? 1 : 1 - 2 ** (-10 * x);\n}\n\nexport class InterludeDots implements HasElement, Disposable {\n\tprivate element: HTMLElement = document.createElement(\"div\");\n\tprivate dot0: HTMLElement = document.createElement(\"span\");\n\tprivate dot1: HTMLElement = document.createElement(\"span\");\n\tprivate dot2: HTMLElement = document.createElement(\"span\");\n\tprivate left = 0;\n\tprivate top = 0;\n\tprivate playing = true;\n\tprivate lastStyle = \"\";\n\tprivate currentInterlude?: [number, number];\n\tprivate currentTime = 0;\n\tprivate targetBreatheDuration = 1500;\n\tconstructor() {\n\t\tthis.element.className = styles.interludeDots;\n\t\tthis.element.appendChild(this.dot0);\n\t\tthis.element.appendChild(this.dot1);\n\t\tthis.element.appendChild(this.dot2);\n\t}\n\tgetElement(): HTMLElement {\n\t\treturn this.element;\n\t}\n\tsetTransform(left: number = this.left, top: number = this.top): void {\n\t\tthis.left = left;\n\t\tthis.top = top;\n\t\tthis.update();\n\t}\n\tsetInterlude(interlude?: [number, number]): void {\n\t\tthis.currentInterlude = interlude;\n\t\tthis.currentTime = interlude?.[0] ?? 0;\n\t\tif (interlude) {\n\t\t\tthis.element.classList.add(styles.enabled);\n\t\t} else {\n\t\t\tthis.element.classList.remove(styles.enabled);\n\t\t}\n\t}\n\tpause(): void {\n\t\tthis.playing = false;\n\t\tthis.element.classList.remove(styles.playing);\n\t}\n\tresume(): void {\n\t\tthis.playing = true;\n\t\tthis.element.classList.add(styles.playing);\n\t}\n\tupdate(delta = 0): void {\n\t\tif (!this.playing) return;\n\t\tthis.currentTime += delta;\n\t\tlet curStyle = \"\";\n\n\t\tcurStyle += `transform:translate(${this.left.toFixed(\n\t\t\t2,\n\t\t)}px, ${this.top.toFixed(2)}px)`;\n\n\t\t// 计算缩放大小\n\n\t\tif (this.currentInterlude) {\n\t\t\tconst interludeDuration =\n\t\t\t\tthis.currentInterlude[1] - this.currentInterlude[0];\n\t\t\tconst currentDuration = this.currentTime - this.currentInterlude[0];\n\t\t\tif (currentDuration <= interludeDuration) {\n\t\t\t\tconst breatheDuration =\n\t\t\t\t\tinterludeDuration /\n\t\t\t\t\tMath.ceil(interludeDuration / this.targetBreatheDuration);\n\t\t\t\tlet scale = 1;\n\t\t\t\tlet globalOpacity = 1;\n\n\t\t\t\tscale *=\n\t\t\t\t\tMath.sin(1.5 * Math.PI - (currentDuration / breatheDuration) * 2) /\n\t\t\t\t\t\t20 +\n\t\t\t\t\t1;\n\n\t\t\t\tif (currentDuration < 2000) {\n\t\t\t\t\tscale *= easeOutExpo(currentDuration / 2000);\n\t\t\t\t}\n\n\t\t\t\tif (currentDuration < 500) {\n\t\t\t\t\tglobalOpacity = 0;\n\t\t\t\t} else if (currentDuration < 1000) {\n\t\t\t\t\tglobalOpacity *= (currentDuration - 500) / 500;\n\t\t\t\t}\n\n\t\t\t\tif (interludeDuration - currentDuration < 750) {\n\t\t\t\t\tscale *=\n\t\t\t\t\t\t1 -\n\t\t\t\t\t\teaseInOutBack(\n\t\t\t\t\t\t\t(750 - (interludeDuration - currentDuration)) / 750 / 2,\n\t\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (interludeDuration - currentDuration < 375) {\n\t\t\t\t\tglobalOpacity *= clamp01((interludeDuration - currentDuration) / 375);\n\t\t\t\t}\n\n\t\t\t\tconst dotsDuration = clampPositive(interludeDuration - 750);\n\n\t\t\t\tscale = clampPositive(scale) * 0.7;\n\n\t\t\t\tcurStyle += ` scale(${scale})`;\n\n\t\t\t\tconst dot0Opacity = clamp(\n\t\t\t\t\t0.25,\n\t\t\t\t\t((currentDuration * 3) / dotsDuration) * 0.75,\n\t\t\t\t\t1,\n\t\t\t\t);\n\t\t\t\tconst dot1Opacity = clamp(\n\t\t\t\t\t0.25,\n\t\t\t\t\t(((currentDuration - dotsDuration / 3) * 3) / dotsDuration) * 0.75,\n\t\t\t\t\t1,\n\t\t\t\t);\n\t\t\t\tconst dot2Opacity = clamp(\n\t\t\t\t\t0.25,\n\t\t\t\t\t(((currentDuration - (dotsDuration / 3) * 2) * 3) / dotsDuration) *\n\t\t\t\t\t\t0.75,\n\t\t\t\t\t1,\n\t\t\t\t);\n\n\t\t\t\tthis.dot0.style.opacity = `${clamp01(globalOpacity * dot0Opacity)}`;\n\t\t\t\tthis.dot1.style.opacity = `${clamp01(globalOpacity * dot1Opacity)}`;\n\t\t\t\tthis.dot2.style.opacity = `${clamp01(globalOpacity * dot2Opacity)}`;\n\t\t\t} else {\n\t\t\t\tcurStyle += \" scale(0)\";\n\t\t\t\tthis.dot0.style.opacity = \"0\";\n\t\t\t\tthis.dot1.style.opacity = \"0\";\n\t\t\t\tthis.dot2.style.opacity = \"0\";\n\t\t\t}\n\n\t\t\tcurStyle += \";\";\n\n\t\t\tif (this.lastStyle !== curStyle) {\n\t\t\t\tthis.element.setAttribute(\"style\", curStyle);\n\t\t\t\tthis.lastStyle = curStyle;\n\t\t\t}\n\t\t}\n\t}\n\tdispose(): void {\n\t\tthis.element.remove();\n\t}\n}\n","/**\n * @fileoverview\n * @see https://github.com/wilsonpage/fastdom/blob/master/fastdom.js\n */\n\ninterface Task<T> {\n\ttask: () => T;\n\tresolve: (value: T) => void;\n\treject: (reason?: unknown) => void;\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: util functions\nconst measureTasks: Task<any>[] = [];\n// biome-ignore lint/suspicious/noExplicitAny: util functions\nconst mutateTasks: Task<any>[] = [];\nlet scheduled = false;\n\nfunction onFlush() {\n\tlet tmp = mutateTasks.shift();\n\twhile (tmp) {\n\t\ttry {\n\t\t\ttmp.resolve(tmp.task());\n\t\t} catch (error) {\n\t\t\ttmp.reject(error);\n\t\t}\n\t\ttmp = mutateTasks.shift();\n\t}\n\ttmp = measureTasks.shift();\n\twhile (tmp) {\n\t\ttry {\n\t\t\ttmp.resolve(tmp.task());\n\t\t} catch (error) {\n\t\t\ttmp.reject(error);\n\t\t}\n\t\ttmp = measureTasks.shift();\n\t}\n\tscheduled = false;\n}\n\nfunction scheduleFlush() {\n\tif (!scheduled) {\n\t\tscheduled = true;\n\t\trequestAnimationFrame(onFlush);\n\t}\n}\n\nexport function measure<T>(callback: () => T): Promise<T> {\n\tconst task: Task<T> = {\n\t\ttask: callback,\n\t\tresolve: () => {},\n\t\treject: () => {},\n\t};\n\tconst promise = new Promise<T>((resolve, reject) => {\n\t\ttask.resolve = resolve;\n\t\ttask.reject = reject;\n\t});\n\tmeasureTasks.push(task);\n\tscheduleFlush();\n\treturn promise;\n}\n\nexport function mutate(callback: () => void): Promise<unknown> {\n\tconst task: Task<void> = {\n\t\ttask: callback,\n\t\tresolve: () => {},\n\t\treject: () => {},\n\t};\n\tconst promise = new Promise((resolve, reject) => {\n\t\ttask.resolve = resolve;\n\t\ttask.reject = reject;\n\t});\n\tmutateTasks.push(task);\n\tscheduleFlush();\n\treturn promise;\n}\n","export function derivative(f: (x: number) => number) {\n\tconst h = 0.001;\n\treturn (x: number): number => (f(x + h) - f(x - h)) / (2 * h);\n}\n\nexport function getVelocity(f: (t: number) => number): (t: number) => number {\n\treturn derivative(f);\n}\n","import { getVelocity } from \"./derivative.ts\";\n\n/** MIT License github.com/pushkine/ */\nexport interface SpringParams {\n\tmass: number; // = 1.0\n\tdamping: number; // = 10.0\n\tstiffness: number; // = 100.0\n\tsoft: boolean; // = false\n}\n\ntype seconds = number;\n\nexport class Spring {\n\tprivate currentPosition = 0;\n\tprivate targetPosition = 0;\n\tprivate currentTime = 0;\n\tprivate params: Partial<SpringParams> = {};\n\tprivate currentSolver: (t: seconds) => number;\n\tprivate getV: (t: seconds) => number;\n\tprivate getV2: (t: seconds) => number;\n\tprivate queueParams:\n\t\t| (Partial<SpringParams> & {\n\t\t\t\ttime: number;\n\t\t })\n\t\t| undefined;\n\tprivate queuePosition:\n\t\t| {\n\t\t\t\ttime: number;\n\t\t\t\tposition: number;\n\t\t }\n\t\t| undefined;\n\tconstructor(currentPosition = 0) {\n\t\tthis.targetPosition = currentPosition;\n\t\tthis.currentPosition = this.targetPosition;\n\t\tthis.currentSolver = () => this.targetPosition;\n\t\tthis.getV = () => 0;\n\t\tthis.getV2 = () => 0;\n\t}\n\tprivate resetSolver() {\n\t\tconst curV = this.getV(this.currentTime);\n\t\tthis.currentTime = 0;\n\t\tthis.currentSolver = solveSpring(\n\t\t\tthis.currentPosition,\n\t\t\tcurV,\n\t\t\tthis.targetPosition,\n\t\t\t0,\n\t\t\tthis.params,\n\t\t);\n\t\tthis.getV = getVelocity(this.currentSolver);\n\t\tthis.getV2 = getVelocity(this.getV);\n\t}\n\tarrived(): boolean {\n\t\treturn (\n\t\t\tMath.abs(this.targetPosition - this.currentPosition) < 0.01 &&\n\t\t\tthis.getV(this.currentTime) < 0.01 &&\n\t\t\tthis.getV2(this.currentTime) < 0.01 &&\n\t\t\tthis.queueParams === undefined &&\n\t\t\tthis.queuePosition === undefined\n\t\t);\n\t}\n\tsetPosition(targetPosition: number): void {\n\t\tthis.targetPosition = targetPosition;\n\t\tthis.currentPosition = targetPosition;\n\t\tthis.currentSolver = () => this.targetPosition;\n\t\tthis.getV = () => 0;\n\t\tthis.getV2 = () => 0;\n\t}\n\tupdate(delta = 0): void {\n\t\tthis.currentTime += delta;\n\t\tthis.currentPosition = this.currentSolver(this.currentTime);\n\t\tif (this.queueParams) {\n\t\t\tthis.queueParams.time -= delta;\n\t\t\tif (this.queueParams.time <= 0) {\n\t\t\t\tthis.updateParams({\n\t\t\t\t\t...this.queueParams,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tif (this.queuePosition) {\n\t\t\tthis.queuePosition.time -= delta;\n\t\t\tif (this.queuePosition.time <= 0) {\n\t\t\t\tthis.setTargetPosition(this.queuePosition.position);\n\t\t\t}\n\t\t}\n\t\tif (this.arrived()) {\n\t\t\tthis.setPosition(this.targetPosition);\n\t\t}\n\t}\n\tupdateParams(params: Partial<SpringParams>, delay = 0): void {\n\t\tif (delay > 0) {\n\t\t\tthis.queueParams = {\n\t\t\t\t...(this.queuePosition ?? {}),\n\t\t\t\t...params,\n\t\t\t\ttime: delay,\n\t\t\t};\n\t\t} else {\n\t\t\tthis.queuePosition = undefined;\n\t\t\tthis.params = {\n\t\t\t\t...this.params,\n\t\t\t\t...params,\n\t\t\t};\n\t\t\tthis.resetSolver();\n\t\t}\n\t}\n\tsetTargetPosition(targetPosition: number, delay = 0): void {\n\t\tif (delay > 0) {\n\t\t\tthis.queuePosition = {\n\t\t\t\t...(this.queuePosition ?? {}),\n\t\t\t\tposition: targetPosition,\n\t\t\t\ttime: delay,\n\t\t\t};\n\t\t} else {\n\t\t\tthis.queuePosition = undefined;\n\t\t\tthis.targetPosition = targetPosition;\n\t\t\tthis.resetSolver();\n\t\t}\n\t}\n\tgetCurrentPosition(): number {\n\t\treturn this.currentPosition;\n\t}\n}\n\nfunction solveSpring(\n\tfrom: number,\n\tvelocity: number,\n\tto: number,\n\tdelay: seconds = 0,\n\tparams?: Partial<SpringParams>,\n): (t: seconds) => number {\n\tconst soft = params?.soft ?? false;\n\tconst stiffness = params?.stiffness ?? 100;\n\tconst damping = params?.damping ?? 10;\n\tconst mass = params?.mass ?? 1;\n\tconst delta = to - from;\n\tif (soft || 1.0 <= damping / (2.0 * Math.sqrt(stiffness * mass))) {\n\t\tconst angular_frequency = -Math.sqrt(stiffness / mass);\n\t\tconst leftover = -angular_frequency * delta - velocity;\n\t\treturn (t: seconds) => {\n\t\t\tt -= delay;\n\t\t\tif (t < 0) return from;\n\t\t\treturn to - (delta + t * leftover) * Math.E ** (t * angular_frequency);\n\t\t};\n\t}\n\tconst damping_frequency = Math.sqrt(4.0 * mass * stiffness - damping ** 2.0);\n\tconst leftover =\n\t\t(damping * delta - 2.0 * mass * velocity) / damping_frequency;\n\tconst dfm = (0.5 * damping_frequency) / mass;\n\tconst dm = -(0.5 * damping) / mass;\n\treturn (t: seconds) => {\n\t\tt -= delay;\n\t\tif (t < 0) return from;\n\t\treturn (\n\t\t\tto -\n\t\t\t(Math.cos(t * dfm) * delta + Math.sin(t * dfm) * leftover) *\n\t\t\t\tMath.E ** (t * dm)\n\t\t);\n\t};\n}\n","import type { Disposable, HasElement } from \"#interfaces\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { measure } from \"#utils/schedule.ts\";\nimport { Spring } from \"#utils/spring.ts\";\nimport type { LyricPlayerBase } from \".\";\n\ninterface LineTransforms {\n\tposX: Spring;\n\tposY: Spring;\n}\n\nexport class BottomLineEl implements HasElement, Disposable {\n\tprivate element: HTMLElement = document.createElement(\"div\");\n\tprivate left = 0;\n\tprivate top = 0;\n\tprivate delay = 0;\n\t// 由 LyricPlayer 来设置\n\tlineSize: [number, number] = [0, 0];\n\treadonly lineTransforms: LineTransforms = {\n\t\tposX: new Spring(0),\n\t\tposY: new Spring(0),\n\t};\n\tprivate isFocused = false;\n\tprivate blur = 0;\n\tconstructor(private lyricPlayer: LyricPlayerBase) {\n\t\tthis.element.setAttribute(\n\t\t\t\"class\",\n\t\t\t`${styles.lyricLine} ${styles.bottomLine}`,\n\t\t);\n\t\tthis.element.dataset.bottomLine = \"true\";\n\t\tthis.rebuildStyle();\n\t}\n\tasync measureSize(): Promise<[number, number]> {\n\t\tconst size: [number, number] = await measure(() => [\n\t\t\tthis.element.clientWidth,\n\t\t\tthis.element.clientHeight,\n\t\t]);\n\t\treturn size;\n\t}\n\tprivate lastStyle = \"\";\n\tshow(): void {\n\t\tthis.rebuildStyle();\n\t}\n\thide(): void {\n\t\tthis.rebuildStyle();\n\t}\n\tsetFocused(focused: boolean): void {\n\t\tif (this.isFocused !== focused) {\n\t\t\tthis.isFocused = focused;\n\t\t\tif (focused) {\n\t\t\t\tthis.element.dataset.focused = \"true\";\n\t\t\t} else {\n\t\t\t\tdelete this.element.dataset.focused;\n\t\t\t}\n\t\t}\n\t}\n\tprivate rebuildStyle() {\n\t\tlet style = `transform:translate(${this.lineTransforms.posX\n\t\t\t.getCurrentPosition()\n\t\t\t.toFixed(2)}px,${this.lineTransforms.posY\n\t\t\t.getCurrentPosition()\n\t\t\t.toFixed(2)}px);`;\n\n\t\tif (!this.lyricPlayer.getEnableSpring() && this.isInSight) {\n\t\t\tstyle += `transition-delay:${this.delay}ms;`;\n\t\t}\n\n\t\tstyle += `filter:blur(${Math.min(5, this.blur)}px);`;\n\n\t\tif (style !== this.lastStyle) {\n\t\t\tthis.lastStyle = style;\n\t\t\tthis.element.setAttribute(\"style\", style);\n\t\t}\n\t}\n\tgetElement(): HTMLElement {\n\t\treturn this.element;\n\t}\n\tsetTransform(\n\t\tleft: number = this.left,\n\t\ttop: number = this.top,\n\t\tblur = 0,\n\t\tforce = false,\n\t\tdelay = 0,\n\t): void {\n\t\tthis.left = left;\n\t\tthis.top = top;\n\t\tthis.delay = (delay * 1000) | 0;\n\n\t\tif (force || !this.lyricPlayer.getEnableSpring()) {\n\t\t\tthis.blur = Math.min(32, blur);\n\t\t\tif (force) this.element.classList.add(styles.tmpDisableTransition);\n\t\t\tthis.lineTransforms.posX.setPosition(left);\n\t\t\tthis.lineTransforms.posY.setPosition(top);\n\t\t\tif (!this.lyricPlayer.getEnableSpring()) this.show();\n\t\t\telse this.rebuildStyle();\n\t\t\tif (force)\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tthis.element.classList.remove(styles.tmpDisableTransition);\n\t\t\t\t});\n\t\t} else {\n\t\t\tthis.blur = Math.min(5, blur);\n\t\t\tthis.lineTransforms.posX.setTargetPosition(left, delay);\n\t\t\tthis.lineTransforms.posY.setTargetPosition(top, delay);\n\t\t}\n\t}\n\tupdate(delta = 0): void {\n\t\tif (!this.lyricPlayer.getEnableSpring()) return;\n\t\tthis.lineTransforms.posX.update(delta);\n\t\tthis.lineTransforms.posY.update(delta);\n\t\tif (this.isInSight) {\n\t\t\tthis.show();\n\t\t} else {\n\t\t\tthis.hide();\n\t\t}\n\t}\n\tget isInSight(): boolean {\n\t\tconst l = this.lineTransforms.posX.getCurrentPosition();\n\t\tconst t = this.lineTransforms.posY.getCurrentPosition();\n\t\tconst r = l + this.lineSize[0];\n\t\tconst b = t + this.lineSize[1];\n\t\tconst pr = this.lyricPlayer.size[0];\n\t\tconst pb = this.lyricPlayer.size[1];\n\t\treturn !(l > pr || t > pb || r < 0 || b < 0);\n\t}\n\tdispose(): void {\n\t\tthis.element.remove();\n\t}\n}\n","type ValueOf<T extends Record<PropertyKey, unknown>> = T[keyof T];\n\n/** 歌词中不雅用语的掩码模式 */\nexport const MaskObsceneWordsMode = {\n\t/** 禁用任何不雅用语掩码 */\n\tDisabled: \"\",\n\t/** 完全掩码所有不雅用语 */\n\tFullMask: \"full-mask\",\n\t/** 保留首尾字符,屏蔽中间字符 */\n\tPartialMask: \"partial-mask\",\n} as const;\n\n/** 歌词中不雅用语的掩码模式枚举类型,见 {@link MaskObsceneWordsMode} */\nexport type MaskObsceneWordsMode = ValueOf<typeof MaskObsceneWordsMode>;\n\n/**\n * 歌词行的渲染模式\n * @internal\n */\nexport const LyricLineRenderMode = {\n\tSOLID: 0,\n\tGRADIENT: 1,\n} as const;\n\n/**\n * 歌词行的渲染模式枚举类型,见 {@link LyricLineRenderMode}\n * @internal\n */\nexport type LyricLineRenderMode = ValueOf<typeof LyricLineRenderMode>;\n\n/** 布局对齐锚点 */\nexport const LayoutAlignAnchor = {\n\tTop: \"top\",\n\tCenter: \"center\",\n\tBottom: \"bottom\",\n} as const;\n\n/** 布局对齐锚点枚举类型,见 {@link LayoutAlignAnchor} */\nexport type LayoutAlignAnchor = ValueOf<typeof LayoutAlignAnchor>;\n","import { clamp } from \"#utils/clamp.ts\";\nimport type { SpringParams } from \"#utils/spring.ts\";\nimport type { LayoutAlignAnchor } from \"./consts.ts\";\nimport type { LyricLineGroupBase } from \"./group.ts\";\nimport type { PlayerTimelineState } from \"./timeline.ts\";\n\n/**\n * 播放器布局状态。\n *\n * 这部分状态保存布局计算阶段所需的配置项与缓存值,\n * 例如对齐方式、间奏点尺寸、上一轮布局命中的目标行等。\n * 不描述播放时间线或用户滚动交互,仅记录当前歌词排布。\n */\nexport interface PlayerLayoutState {\n\t/** 间奏点元素当前测量得到的尺寸 */\n\tinterludeDotsSize: [number, number];\n\t/** 上一轮布局实际对齐的目标歌词行索引 */\n\ttargetAlignIndex: number;\n\t/** 上一轮布局时是否处于间奏区间 */\n\tlastInterludeState: boolean;\n\t/** 当前歌词目标行的对齐锚点 */\n\talignAnchor: LayoutAlignAnchor;\n\t/** 当前歌词目标行在播放器高度中的相对对齐位置 */\n\talignPosition: number;\n\t/** 视口上下额外保留的预渲染距离,单位为像素 */\n\toverscanPx: number;\n}\n\n/**\n * 当前命中的间奏区间信息。\n *\n * 当播放器检测到当前时间处于两句歌词之间的较长空档期时,\n * 会生成该结构,用于驱动间奏点动画的显示位置与时间范围。\n */\nexport interface PlayerInterlude {\n\t/** 间奏动画的开始时间 */\n\tstartTime: number;\n\t/** 间奏动画的结束时间 */\n\tendTime: number;\n\t/** 间奏点应插入到哪一行之后;`-1` 表示位于第一行之前 */\n\tanchorLineIndex: number;\n\t/** 间奏结束后的下一句是否为对唱歌词 */\n\tisNextDuet: boolean;\n}\n\n/** {@link computeCurrentInterlude} 的参数类型 */\nexport interface ComputeCurrentInterludeInput {\n\tcurrentTime: number;\n\tscrollToIndex: number;\n\tcurrentGroups: LyricLineGroupBase[];\n}\n\n/**\n * 根据当前时间与当前目标行,计算当前是否处于某个可展示的间奏区间。\n *\n * 仅识别时间轴上的间奏空档,不涉及具体 DOM 元素的创建与摆放。\n * 若当前不应展示间奏动画,则返回 `undefined`。\n */\nexport function computeCurrentInterlude(\n\tinput: ComputeCurrentInterludeInput,\n): PlayerInterlude | undefined {\n\tconst currentTime = input.currentTime + 20;\n\tconst currentIndex = input.scrollToIndex;\n\tconst groups = input.currentGroups;\n\n\tconst checkGap = (k: number): PlayerInterlude | undefined => {\n\t\tif (k < -1 || k >= groups.length - 1) return undefined;\n\n\t\tconst prevGroup = k === -1 ? null : groups[k];\n\t\tconst nextGroup = groups[k + 1];\n\n\t\tconst gapStart = prevGroup ? prevGroup.endTime : 0;\n\t\tconst gapEnd = Math.max(gapStart, nextGroup.startTime - 250);\n\n\t\tif (gapEnd - gapStart < 4000) return undefined;\n\n\t\tif (gapEnd > currentTime && gapStart < currentTime) {\n\t\t\treturn {\n\t\t\t\tstartTime: Math.max(gapStart, currentTime),\n\t\t\t\tendTime: gapEnd,\n\t\t\t\tanchorLineIndex: k,\n\t\t\t\tisNextDuet: nextGroup.mainLine.getLine().isDuet,\n\t\t\t};\n\t\t}\n\t\treturn undefined;\n\t};\n\n\treturn (\n\t\tcheckGap(currentIndex - 1) ||\n\t\tcheckGap(currentIndex) ||\n\t\tcheckGap(currentIndex + 1)\n\t);\n}\n\n/**\n * {@link computeLinePosYSpringParams} 的参数类型,\n * 用于决定当前歌词纵向滚动动画的弹簧参数。\n */\nexport interface ComputeLinePosYSpringParamsInput {\n\t/** 是否启用弹簧动画 */\n\tenabled: boolean;\n\t/** 当前用于布局的歌词数据 */\n\tcurrentGroups: LyricLineGroupBase[];\n\t/** 当前目标对齐行索引 */\n\tscrollToIndex: number;\n\t/** 是否处于 seeking 模式 */\n\tisSeeking: boolean;\n\t/** 是否处于间奏区间 */\n\tisInterludeActive: boolean;\n}\n\n/** {@link computeLinePosYSpringParams} 的结果类型 */\nexport interface ComputeLinePosYSpringParamsResult {\n\t/** 是否需要更新纵向弹簧参数 */\n\tshouldUpdate: boolean;\n\t/** 若需要更新,则返回新的参数 */\n\tparams?: Partial<SpringParams>;\n}\n\n/**\n * 根据当前播放上下文计算歌词纵向滚动动画的弹簧参数。\n *\n * 其策略为:\n * - seeking 或间奏时使用更稳定的固定参数\n * - 普通播放时根据相邻歌词的时间间隔动态调整 stiffness / damping\n */\nexport function computeLinePosYSpringParams(\n\tinput: ComputeLinePosYSpringParamsInput,\n): ComputeLinePosYSpringParamsResult {\n\tconst {\n\t\tenabled,\n\t\tcurrentGroups,\n\t\tscrollToIndex,\n\t\tisSeeking,\n\t\tisInterludeActive,\n\t} = input;\n\n\tif (!enabled || currentGroups.length === 0) {\n\t\treturn { shouldUpdate: false };\n\t}\n\n\tif (isSeeking || isInterludeActive) {\n\t\treturn {\n\t\t\tshouldUpdate: true,\n\t\t\tparams: { stiffness: 90, damping: 15 },\n\t\t};\n\t}\n\n\tconst currentGroup = currentGroups[scrollToIndex];\n\tconst prevGroup = currentGroups[scrollToIndex - 1];\n\n\tif (!currentGroup || !prevGroup) {\n\t\treturn { shouldUpdate: false };\n\t}\n\n\tconst interval = currentGroup.startTime - prevGroup.startTime;\n\n\tconst MIN_INTERVAL = 100;\n\tconst MAX_INTERVAL = 800;\n\tconst clampedInterval = clamp(interval, MIN_INTERVAL, MAX_INTERVAL);\n\n\tconst MAX_STIFFNESS = 220;\n\tconst MIN_STIFFNESS = 170;\n\n\tlet ratio =\n\t\t1 - (clampedInterval - MIN_INTERVAL) / (MAX_INTERVAL - MIN_INTERVAL);\n\n\tratio = ratio ** 0.2;\n\n\tconst targetStiffness =\n\t\tMIN_STIFFNESS + ratio * (MAX_STIFFNESS - MIN_STIFFNESS);\n\n\tconst dampingMultiplier = 2.2;\n\tconst targetDamping = Math.sqrt(targetStiffness) * dampingMultiplier;\n\n\treturn {\n\t\tshouldUpdate: true,\n\t\tparams: {\n\t\t\tstiffness: targetStiffness,\n\t\t\tdamping: targetDamping,\n\t\t},\n\t};\n}\n\n/**\n * {@link computeGroupPresentation} 的参数类型。\n *\n * 描述一行歌词在当前布局上下文中的全部关键信息,\n * 用于计算其视觉呈现结果。\n */\nexport interface ComputeGroupPresentationInput {\n\t/** 当前歌词组索引 */\n\tgroupIndex: number;\n\t/** 当前目标对齐行索引 */\n\tscrollToIndex: number;\n\t/** 当前缓冲区({@link PlayerTimelineState.bufferedGroups})中最靠后的歌词行索引 */\n\tlatestIndex: number;\n\t/** 当前歌词行是否在缓冲集合内 */\n\thasBuffered: boolean;\n\t/** 是否启用隐藏已播放行 */\n\thidePassedLines: boolean;\n\t/** 是否处于播放状态 */\n\tisPlaying: boolean;\n\t/** 当前歌词是否为非逐词歌词 */\n\tisNonDynamic: boolean;\n\t/** 是否启用模糊效果 */\n\tenableBlur: boolean;\n\t/** 是否正在进行滚动交互 */\n\tisUserScrolling: boolean;\n\t/** 是否处于紧凑布局环境,例如窄屏 */\n\tisCompact: boolean;\n\t/** 当前命中的间奏区间信息 */\n\tinterlude?: PlayerInterlude;\n}\n\n/** {@link computeGroupPresentation} 的结果类型 */\nexport interface ComputeGroupPresentationResult {\n\t/** 当前歌词行是否应视为活跃行 */\n\tisActive: boolean;\n\t/** 当前歌词行的目标不透明度 */\n\ttargetOpacity: number;\n\t/** 当前歌词行的目标模糊值 */\n\tblurLevel: number;\n}\n\n/**\n * 计算一组歌词在当前布局中的视觉呈现参数。\n *\n * 根据播放状态、缓冲状态、布局模式与间奏信息,\n * 生成一组歌词最终应使用的活跃状态、不透明度与模糊值。\n */\nexport function computeGroupPresentation(\n\tinput: ComputeGroupPresentationInput,\n): ComputeGroupPresentationResult {\n\tconst {\n\t\tgroupIndex,\n\t\tscrollToIndex,\n\t\tlatestIndex,\n\t\thasBuffered,\n\t\thidePassedLines,\n\t\tisPlaying,\n\t\tisNonDynamic,\n\t\tenableBlur,\n\t\tisUserScrolling,\n\t\tisCompact,\n\t\tinterlude,\n\t} = input;\n\n\tconst isActive =\n\t\thasBuffered || (groupIndex >= scrollToIndex && groupIndex < latestIndex);\n\n\tconst blurLevel = computeLineBlur({\n\t\tenableBlur,\n\t\tisUserScrolling,\n\t\tisActive,\n\t\titemIndex: groupIndex,\n\t\tscrollToIndex,\n\t\tlatestIndex,\n\t\tisCompact,\n\t});\n\n\tlet targetOpacity: number;\n\tif (hidePassedLines) {\n\t\tif (\n\t\t\tgroupIndex <\n\t\t\t\t(interlude ? interlude.anchorLineIndex + 1 : scrollToIndex) &&\n\t\t\tisPlaying\n\t\t) {\n\t\t\t// 为了避免浏览器优化,这里使用了一个极小但不为零的值(几乎不可见)\n\t\t\ttargetOpacity = 1e-4;\n\t\t} else if (hasBuffered) {\n\t\t\ttargetOpacity = 0.85;\n\t\t} else {\n\t\t\ttargetOpacity = isNonDynamic ? 0.2 : 1;\n\t\t}\n\t} else if (hasBuffered) {\n\t\ttargetOpacity = 0.85;\n\t} else {\n\t\ttargetOpacity = isNonDynamic ? 0.2 : 1;\n\t}\n\n\treturn { isActive, targetOpacity, blurLevel };\n}\n\n/** {@link computeLineBlur} 的参数类型 */\nexport interface ComputeLineBlurInput {\n\t/** 是否启用了模糊效果 */\n\tenableBlur: boolean;\n\t/** 用户是否正在滚动 */\n\tisUserScrolling: boolean;\n\t/** 当前项是否活跃 */\n\tisActive: boolean;\n\t/** 当前项索引 */\n\titemIndex: number;\n\t/** 当前目标对齐行索引 */\n\tscrollToIndex: number;\n\t/** 缓冲区中最靠后的歌词行索引 */\n\tlatestIndex: number;\n\t/** 是否处于紧凑布局环境,例如窄屏 */\n\tisCompact: boolean;\n}\n\n/**\n * 计算一行歌词在当前布局中的模糊等级。\n *\n * 越远离当前对齐区域的歌词会得到更高的模糊值;\n * 活跃行、滚动交互中或关闭模糊效果时返回 `0`。\n */\nexport function computeLineBlur(input: ComputeLineBlurInput): number {\n\tconst {\n\t\tenableBlur,\n\t\tisUserScrolling,\n\t\tisActive,\n\t\titemIndex,\n\t\tscrollToIndex,\n\t\tlatestIndex,\n\t\tisCompact,\n\t} = input;\n\n\tif (!enableBlur || isUserScrolling || isActive) {\n\t\treturn 0;\n\t}\n\n\tlet blurLevel = 1;\n\n\tif (itemIndex < scrollToIndex) {\n\t\tblurLevel += Math.abs(scrollToIndex - itemIndex) + 1;\n\t} else {\n\t\tblurLevel += Math.abs(itemIndex - Math.max(scrollToIndex, latestIndex));\n\t}\n\n\treturn isCompact ? blurLevel * 0.8 : blurLevel;\n}\n","import { clamp } from \"#utils/clamp.ts\";\n\n/**\n * 播放器滚动状态。\n *\n * 这部分状态描述用户手势/滚轮滚动产生的临时偏移,以及当前允许滚动的范围。\n * 改状态仅记录用户如何把当前视图上下拖动,不决定应该滚动到哪一行,\n * 后者由时间线状态与布局计算共同决定。\n */\nexport interface PlayerScrollState {\n\t/** 允许的滚动偏移范围 */\n\tscrollBoundary: {\n\t\t/** 允许的最小偏移量 */\n\t\tminOffset: number;\n\t\t/** 允许的最大偏移量 */\n\t\tmaxOffset: number;\n\t};\n\t/** 当前用户滚动带来的额外偏移量 */\n\tscrollOffset: number;\n\t/** 是否允许用户通过手势或滚轮滚动歌词视图 */\n\tallowScroll: boolean;\n\t/** 是否处于用户滚动过,尚未回归自动对齐的状态 */\n\tisScrolled: boolean;\n\t/** 是否正在进行滚动交互或惯性滚动 */\n\tisUserScrolling: boolean;\n}\n\n/**\n * 将滚动偏移量限制在当前允许的滚动边界内。\n *\n * 当手势滚动、滚轮滚动或惯性滚动更新了 {@link PlayerScrollState.scrollOffset}\n * 后,应调用本函数以避免视图越界。\n */\nexport function clampPlayerScrollOffset(scrollState: PlayerScrollState): void {\n\tscrollState.scrollOffset = clamp(\n\t\tscrollState.scrollOffset,\n\t\tscrollState.scrollBoundary.minOffset,\n\t\tscrollState.scrollBoundary.maxOffset,\n\t);\n}\n\n/**\n * 重置滚动状态到未发生用户滚动时的初始状态。\n *\n * 本函数会清除当前偏移,并结束“已滚动”与“正在滚动”的标记;\n * **不会清理**外部持有的计时器或事件监听器。\n */\nexport function resetPlayerScrollState(scrollState: PlayerScrollState): void {\n\tscrollState.isScrolled = false;\n\tscrollState.scrollOffset = 0;\n\tscrollState.isUserScrolling = false;\n}\n\n/**\n * {@link attachPlayerScrollHandlers} 所需的宿主回调。\n *\n * 这些回调将滚动模块与具体播放器实现解耦:\n * 滚动模块只负责处理输入事件和更新滚动状态,布局刷新、点击转发等副作用\n * 由宿主决定如何执行。\n */\nexport interface AttachPlayerScrollHandlersCallbacks {\n\t/** 开始一次滚动处理前调用,返回 `false` 可阻止本次滚动 */\n\tonBeginScroll: () => boolean;\n\t/** 一次滚动交互或惯性滚动结束时调用 */\n\tonEndScroll: () => void;\n\t/** 请求宿主重新布局 */\n\tonLayout: (sync: boolean, force: boolean) => void;\n\t/** 判断某个点击目标是否仍属于当前播放器视图 */\n\tcontainsTarget: (target: Node) => boolean;\n\t/** 将点击事件转发给命中的目标元素 */\n\tclickTarget: (target: HTMLElement) => void;\n}\n\n/**\n * 向指定元素挂载歌词滚动相关的交互处理器。\n *\n * 该函数会处理:\n * - 触摸拖拽滚动\n * - 触摸结束后的惯性滚动\n * - 滚轮滚动\n * - 轻触时的点击透传\n *\n * 只更新 {@link PlayerScrollState} 并通过回调通知宿主执行布局或其它副作用,\n * 不直接依赖具体的播放器类实现。\n */\nexport function attachPlayerScrollHandlers(\n\telement: HTMLElement,\n\tscrollState: PlayerScrollState,\n\tcallbacks: AttachPlayerScrollHandlersCallbacks,\n): void {\n\tlet startScrollY = 0;\n\n\tlet startTouchPosY = 0;\n\tlet startTouchStartX = 0;\n\tlet startTouchStartY = 0;\n\n\tlet lastMoveY = 0;\n\tlet startScrollTime = 0;\n\tlet scrollSpeed = 0;\n\tlet curScrollId = 0;\n\n\telement.addEventListener(\"touchstart\", (evt) => {\n\t\tif (callbacks.onBeginScroll()) {\n\t\t\tscrollState.isUserScrolling = true;\n\n\t\t\tevt.preventDefault();\n\t\t\tstartScrollY = scrollState.scrollOffset;\n\n\t\t\tstartTouchPosY = evt.touches[0].screenY;\n\t\t\tlastMoveY = startTouchPosY;\n\n\t\t\tstartTouchStartX = evt.touches[0].screenX;\n\t\t\tstartTouchStartY = evt.touches[0].screenY;\n\n\t\t\tstartScrollTime = Date.now();\n\t\t\tscrollSpeed = 0;\n\n\t\t\tcallbacks.onLayout(true, true);\n\t\t}\n\t});\n\n\telement.addEventListener(\"touchmove\", (evt) => {\n\t\tif (callbacks.onBeginScroll()) {\n\t\t\tevt.preventDefault();\n\t\t\tconst currentY = evt.touches[0].screenY;\n\n\t\t\tconst deltaY = currentY - startTouchPosY;\n\t\t\tscrollState.scrollOffset = startScrollY - deltaY;\n\t\t\tclampPlayerScrollOffset(scrollState);\n\n\t\t\tconst now = Date.now();\n\t\t\tconst dt = now - startScrollTime;\n\t\t\tif (dt > 0) {\n\t\t\t\tscrollSpeed = (currentY - lastMoveY) / dt;\n\t\t\t}\n\t\t\tlastMoveY = currentY;\n\t\t\tstartScrollTime = now;\n\n\t\t\tcallbacks.onLayout(true, true);\n\t\t}\n\t});\n\n\telement.addEventListener(\"touchend\", (evt) => {\n\t\tif (callbacks.onBeginScroll()) {\n\t\t\tevt.preventDefault();\n\n\t\t\tconst touch = evt.changedTouches[0];\n\t\t\tconst moveX = Math.abs(touch.screenX - startTouchStartX);\n\t\t\tconst moveY = Math.abs(touch.screenY - startTouchStartY);\n\n\t\t\tif (moveX < 10 && moveY < 10) {\n\t\t\t\tconst target = document.elementFromPoint(touch.clientX, touch.clientY);\n\t\t\t\tif (target instanceof HTMLElement && callbacks.containsTarget(target)) {\n\t\t\t\t\tcallbacks.clickTarget(target);\n\t\t\t\t}\n\t\t\t\tscrollState.isUserScrolling = false;\n\t\t\t\tcallbacks.onEndScroll();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tstartTouchPosY = 0;\n\t\t\tconst scrollId = ++curScrollId;\n\n\t\t\tif (Math.abs(scrollSpeed) < 0.1) scrollSpeed = 0;\n\n\t\t\tlet lastFrameTime = performance.now();\n\n\t\t\tconst onScrollFrame = (time: number) => {\n\t\t\t\tif (scrollId !== curScrollId) return;\n\n\t\t\t\tconst dt = time - lastFrameTime;\n\t\t\t\tlastFrameTime = time;\n\n\t\t\t\tif (dt <= 0 || dt > 100) {\n\t\t\t\t\trequestAnimationFrame(onScrollFrame);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (Math.abs(scrollSpeed) > 0.05) {\n\t\t\t\t\tscrollState.scrollOffset -= scrollSpeed * dt;\n\n\t\t\t\t\tclampPlayerScrollOffset(scrollState);\n\n\t\t\t\t\tconst frictionFactor = 0.95 ** (dt / 16);\n\t\t\t\t\tscrollSpeed *= frictionFactor;\n\n\t\t\t\t\tcallbacks.onLayout(true, true);\n\n\t\t\t\t\trequestAnimationFrame(onScrollFrame);\n\t\t\t\t} else {\n\t\t\t\t\tscrollState.isUserScrolling = false;\n\t\t\t\t\tcallbacks.onEndScroll();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\trequestAnimationFrame(onScrollFrame);\n\t\t} else {\n\t\t\tscrollState.isUserScrolling = false;\n\t\t}\n\t});\n\n\telement.addEventListener(\n\t\t\"wheel\",\n\t\t(evt) => {\n\t\t\tif (callbacks.onBeginScroll()) {\n\t\t\t\tevt.preventDefault();\n\n\t\t\t\tif (evt.deltaMode === evt.DOM_DELTA_PIXEL) {\n\t\t\t\t\tscrollState.scrollOffset += evt.deltaY;\n\t\t\t\t\tclampPlayerScrollOffset(scrollState);\n\t\t\t\t\tcallbacks.onLayout(true, false);\n\t\t\t\t} else {\n\t\t\t\t\tscrollState.scrollOffset += evt.deltaY * 50;\n\t\t\t\t\tclampPlayerScrollOffset(scrollState);\n\t\t\t\t\tcallbacks.onLayout(false, false);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{ passive: false },\n\t);\n}\n","export const eqSet: <T>(xs: Set<T>, ys: Set<T>) => boolean = (\n\txs,\n\tys,\n): boolean => xs.size === ys.size && [...xs].every((x) => ys.has(x));\n","import { eqSet } from \"#utils/eq-set.ts\";\nimport type { LyricLineGroupBase } from \"./group.ts\";\n\n/**\n * 播放时间线状态。\n *\n * 描述播放器在时间轴上的当前位置,当前处于激活状态的歌词组信息\n */\nexport interface PlayerTimelineState {\n\t/** 当前播放时间,单位为毫秒 */\n\tcurrentTime: number;\n\t/** 上一次提交到时间线状态的播放时间,单位为毫秒 */\n\tlastCurrentTime: number;\n\t/** 热行:当前时间 {@link currentTime} 正在命中的组(含主行+可能的背景行) */\n\thotGroups: Set<number>;\n\t/** 缓冲组:UI 上还保持激活表现的组索引,通常包含热组,和刚结束仍在过渡中的组 */\n\tbufferedGroups: Set<number>;\n\t/** 当前应滚动对齐到的歌词组索引 */\n\tscrollToIndex: number;\n\t/** 是否正在拖拽进度条。若是,更新时丢弃缓冲行,并根据当前时间直接计算热行 */\n\tisSeeking: boolean;\n\t/** 是否处于播放状态 */\n\tisPlaying: boolean;\n\t/** 是否已经完成至少一次初始布局 */\n\tinitialLayoutFinished: boolean;\n}\n\n/** {@link computePlayerTimeState} 的参数类型 */\nexport interface ComputePlayerTimeStateInput {\n\ttime: number;\n\tcurrentGroups: LyricLineGroupBase[];\n\ttimelineState: Readonly<PlayerTimelineState>;\n}\n\n/** {@link computePlayerTimeState} 的返回类型 */\nexport interface ComputePlayerTimeStateResult {\n\t/** 计算后的新热组集合 */\n\tnextHotGroups: Set<number>;\n\t/** 需要新加入热组集合的组索引 */\n\taddedIds: Set<number>;\n\t/** 需要从热组集合中移除的组索引 */\n\tremovedHotIds: Set<number>;\n\t/** 需要从缓冲组集合中移除的组索引 */\n\tremovedBufferedIds: Set<number>;\n}\n\n/**\n * 计算指定时间点的热行/缓冲行状态转移的纯函数。其行为包括:\n *\n * - 根据当前时间和已有的热行状态,计算出新的热行状态,并返回应新增的热行 ID 和应移除的热行 ID\n * - 根据新的热行状态和已有的缓冲行状态,计算出应移除的缓冲行 ID\n */\nexport function computePlayerTimeState(\n\tinput: ComputePlayerTimeStateInput,\n): ComputePlayerTimeStateResult {\n\tconst {\n\t\ttime,\n\t\tcurrentGroups,\n\t\ttimelineState: { hotGroups, bufferedGroups },\n\t} = input;\n\n\tconst nextHotGroups = new Set(hotGroups);\n\tconst addedIds = new Set<number>();\n\tconst removedHotIds = new Set<number>();\n\tconst removedBufferedIds = new Set<number>();\n\n\tfor (const lastHotId of hotGroups) {\n\t\tconst group = currentGroups[lastHotId];\n\t\tif (!group || time < group.startTime || group.endTime <= time) {\n\t\t\tnextHotGroups.delete(lastHotId);\n\t\t\tremovedHotIds.add(lastHotId);\n\t\t}\n\t}\n\n\tfor (let id = 0; id < currentGroups.length; id++) {\n\t\tconst group = currentGroups[id];\n\t\tif (!group) continue;\n\n\t\tif (\n\t\t\tgroup.startTime <= time &&\n\t\t\tgroup.endTime > time &&\n\t\t\t!nextHotGroups.has(id)\n\t\t) {\n\t\t\tnextHotGroups.add(id);\n\t\t\taddedIds.add(id);\n\t\t}\n\t}\n\n\tfor (const id of bufferedGroups) {\n\t\tif (!nextHotGroups.has(id)) {\n\t\t\tremovedBufferedIds.add(id);\n\t\t}\n\t}\n\n\treturn {\n\t\tnextHotGroups,\n\t\taddedIds,\n\t\tremovedHotIds,\n\t\tremovedBufferedIds,\n\t};\n}\n\n/**\n * 在 seeking 场景下,根据当前时间选出应对齐滚动到的目标行索引。\n *\n * 若当前仍存在缓冲行,则优先对齐到最靠前的缓冲行;\n * 否则对齐到第一条开始时间不小于当前时间的歌词行。\n */\nexport function pickScrollToIndexForSeek(\n\ttime: number,\n\tcurrentGroups: LyricLineGroupBase[],\n\tbufferedGroups: ReadonlySet<number>,\n): number {\n\tif (bufferedGroups.size > 0) {\n\t\treturn Math.min(...bufferedGroups);\n\t}\n\tconst foundIndex = currentGroups.findIndex(\n\t\t(group) => group.startTime >= time,\n\t);\n\treturn foundIndex === -1 ? currentGroups.length : foundIndex;\n}\n\n/**\n * {@link commitPlayerTimeState} 的参数类型。\n *\n * 用于将一次时间线状态转移提交回 {@link PlayerTimelineState},\n * 并生成供宿主执行的副作用应用计划。\n */\nexport interface CommitPlayerTimeStateInput {\n\t/** 要被更新的时间线状态对象 */\n\ttimelineState: PlayerTimelineState;\n\t/** 当前播放时间,单位为毫秒 */\n\ttime: number;\n\t/** 当前用于计算的歌词数据 */\n\tcurrentGroups: LyricLineGroupBase[];\n\t/** 底部附加区域当前是否有可见内容 */\n\thasBottomContent: boolean;\n\t/** 由 {@link computePlayerTimeState} 得到的状态转移结果 */\n\tstateResult: ComputePlayerTimeStateResult;\n}\n\n/** {@link commitPlayerTimeState} 的返回类型 */\nexport interface CommitPlayerTimeStateResult {\n\t/** 提交后是否需要重新布局 */\n\tshouldLayout: boolean;\n\t/** 提交后是否需要重置用户滚动状态 */\n\tshouldResetScroll: boolean;\n\t/** 需要启用的歌词组索引列表 */\n\tgroupsToEnable: number[];\n\t/** 需要禁用的歌词组索引列表 */\n\tgroupsToDisable: number[];\n}\n\n/**\n * 提交时间线状态转移的纯函数。\n *\n * 把一次时间线状态转移写回 {@link PlayerTimelineState},\n * 并返回一份供宿主执行的副作用应用计划,例如启用/禁用哪些歌词行、\n * 是否需要重置用户滚动状态、是否需要触发布局。\n */\nexport function commitPlayerTimeState(\n\tinput: CommitPlayerTimeStateInput,\n): CommitPlayerTimeStateResult {\n\tconst { timelineState, time, currentGroups, hasBottomContent, stateResult } =\n\t\tinput;\n\tconst { addedIds, removedHotIds, removedBufferedIds } = stateResult;\n\tconst { isSeeking } = timelineState;\n\n\ttimelineState.currentTime = time;\n\ttimelineState.hotGroups = stateResult.nextHotGroups;\n\n\tlet shouldLayout = false;\n\tlet shouldResetScroll = false;\n\tconst groupsToEnable: number[] = [];\n\tconst groupsToDisable = new Set<number>();\n\n\tif (isSeeking) {\n\t\ttimelineState.bufferedGroups = new Set([...timelineState.hotGroups]);\n\t\ttimelineState.scrollToIndex = pickScrollToIndexForSeek(\n\t\t\ttime,\n\t\t\tcurrentGroups,\n\t\t\ttimelineState.bufferedGroups,\n\t\t);\n\t\tfor (const id of removedHotIds) groupsToDisable.add(id);\n\t\tfor (const id of timelineState.hotGroups) groupsToEnable.push(id);\n\t\tfor (const id of removedBufferedIds) groupsToDisable.add(id);\n\n\t\tshouldResetScroll = true;\n\t\tshouldLayout = true;\n\t} else if (addedIds.size > 0) {\n\t\tfor (const id of addedIds) {\n\t\t\ttimelineState.bufferedGroups.add(id);\n\t\t\tgroupsToEnable.push(id);\n\t\t}\n\t\tfor (const id of removedBufferedIds) {\n\t\t\ttimelineState.bufferedGroups.delete(id);\n\t\t\tgroupsToDisable.add(id);\n\t\t}\n\t\tif (timelineState.bufferedGroups.size > 0) {\n\t\t\ttimelineState.scrollToIndex = Math.min(...timelineState.bufferedGroups);\n\t\t}\n\t\tshouldLayout = true;\n\t} else if (\n\t\tremovedBufferedIds.size > 0 &&\n\t\teqSet(removedBufferedIds, timelineState.bufferedGroups)\n\t) {\n\t\tfor (const id of timelineState.bufferedGroups) {\n\t\t\tif (timelineState.hotGroups.has(id)) continue;\n\t\t\ttimelineState.bufferedGroups.delete(id);\n\t\t\tgroupsToDisable.add(id);\n\t\t}\n\t\tshouldLayout = true;\n\t}\n\n\tif (timelineState.bufferedGroups.size === 0 && currentGroups.length > 0) {\n\t\tconst lastGroup = currentGroups[currentGroups.length - 1];\n\t\tif (time >= lastGroup.endTime) {\n\t\t\tconst targetIndex = hasBottomContent\n\t\t\t\t? currentGroups.length\n\t\t\t\t: currentGroups.length - 1;\n\t\t\tif (timelineState.scrollToIndex !== targetIndex) {\n\t\t\t\ttimelineState.scrollToIndex = targetIndex;\n\t\t\t\tshouldLayout = true;\n\t\t\t}\n\t\t}\n\t}\n\n\ttimelineState.lastCurrentTime = time;\n\n\treturn {\n\t\tshouldLayout,\n\t\tshouldResetScroll,\n\t\tgroupsToEnable,\n\t\tgroupsToDisable: [...groupsToDisable],\n\t};\n}\n","import structuredClone from \"@ungap/structured-clone\";\nimport type {\n\tDisposable,\n\tHasElement,\n\tLyricLine,\n\tLyricWord,\n\tOptimizeLyricOptions,\n} from \"#interfaces\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { clampPositive } from \"#utils/clamp.ts\";\nimport { optimizeLyricLines } from \"#utils/optimize-lyric.ts\";\nimport type { SpringParams } from \"#utils/spring.ts\";\nimport { InterludeDots } from \"../dom/interlude-dots.ts\";\nimport { BottomLineEl } from \"./bottom-line.ts\";\nimport { LayoutAlignAnchor, MaskObsceneWordsMode } from \"./consts.ts\";\nimport type { LyricLineGroupBase } from \"./group.ts\";\nimport {\n\tcomputeCurrentInterlude,\n\tcomputeGroupPresentation,\n\tcomputeLineBlur,\n\tcomputeLinePosYSpringParams,\n\ttype PlayerLayoutState,\n} from \"./layout.ts\";\nimport type { LyricLineBase } from \"./line.ts\";\nimport {\n\tattachPlayerScrollHandlers,\n\ttype PlayerScrollState,\n\tresetPlayerScrollState,\n} from \"./scroll.ts\";\nimport {\n\tcommitPlayerTimeState,\n\tcomputePlayerTimeState,\n\ttype PlayerTimelineState,\n} from \"./timeline.ts\";\n\nexport type { PlayerLayoutState } from \"./layout.ts\";\nexport type { LyricLineBase } from \"./line.ts\";\nexport type { PlayerScrollState } from \"./scroll.ts\";\nexport type { PlayerTimelineState } from \"./timeline.ts\";\n\n/**\n * 歌词播放器的基类,已经包含了有关歌词操作和排版的功能,\n * 子类需要为其实现对应的显示展示操作\n */\nexport abstract class LyricPlayerBase\n\textends EventTarget\n\timplements HasElement, Disposable\n{\n\tprotected element: HTMLElement = document.createElement(\"div\");\n\tabstract get baseFontSize(): number;\n\n\t/** 播放时间线状态 */\n\tprotected timelineState: PlayerTimelineState = {\n\t\tcurrentTime: 0,\n\t\tlastCurrentTime: 0,\n\t\thotGroups: new Set(),\n\t\tbufferedGroups: new Set(),\n\t\tscrollToIndex: 0,\n\t\tisSeeking: false,\n\t\tisPlaying: true,\n\t\tinitialLayoutFinished: false,\n\t};\n\t/** @internal */\n\tlyricGroupElementMap: WeakMap<Element, LyricLineGroupBase> = new WeakMap();\n\tprotected currentLyricLines: LyricLine[] = [];\n\tprotected processedLines: LyricLine[] = [];\n\tprotected lyricLinesIndexes: WeakMap<LyricLineBase, number> = new WeakMap();\n\tprotected isNonDynamic = false;\n\tprotected hasDuetLine = false;\n\tprotected disableSpring = false;\n\tprotected layoutState: PlayerLayoutState = {\n\t\tinterludeDotsSize: [0, 0],\n\t\ttargetAlignIndex: 0,\n\t\tlastInterludeState: false,\n\t\talignAnchor: LayoutAlignAnchor.Center,\n\t\talignPosition: 0.35,\n\t\toverscanPx: 300,\n\t};\n\tprotected interludeDots: InterludeDots = new InterludeDots();\n\tprotected bottomLine: BottomLineEl = new BottomLineEl(this);\n\tprotected enableBlur = true;\n\tprotected enableScale = true;\n\tprotected maskObsceneWords: MaskObsceneWordsMode =\n\t\tMaskObsceneWordsMode.Disabled;\n\tprotected maskObsceneWordChar = \"*\";\n\tprotected hidePassedLines = false;\n\tprotected scrollState: PlayerScrollState = {\n\t\tscrollBoundary: { minOffset: 0, maxOffset: 0 },\n\t\tscrollOffset: 0,\n\t\tallowScroll: true,\n\t\tisScrolled: false,\n\t\tisUserScrolling: false,\n\t};\n\tpublic currentLyricGroups: LyricLineGroupBase[] = [];\n\tlyricGroupSize: WeakMap<LyricLineGroupBase, [number, number]> = new WeakMap();\n\treadonly size: [number, number] = [0, 0];\n\tprotected isPageVisible = true;\n\tprotected optimizeOptions: OptimizeLyricOptions = {};\n\n\t/** 是否强制让背景人声行始终后置(即始终在主歌词下方显示,不前置背景人声) */\n\tprotected alwaysPostpositionBackground = false;\n\n\tprotected posXSpringParams: Partial<SpringParams> = {\n\t\tmass: 1,\n\t\tdamping: 10,\n\t\tstiffness: 100,\n\t};\n\tprotected posYSpringParams: Partial<SpringParams> = {\n\t\tmass: 0.9,\n\t\tdamping: 15,\n\t\tstiffness: 90,\n\t};\n\tprotected scaleSpringParams: Partial<SpringParams> = {\n\t\tmass: 2,\n\t\tdamping: 25,\n\t\tstiffness: 100,\n\t};\n\tprotected scaleForBGSpringParams: Partial<SpringParams> = {\n\t\tmass: 1,\n\t\tdamping: 20,\n\t\tstiffness: 50,\n\t};\n\tprivate onPageShow = () => {\n\t\tthis.isPageVisible = true;\n\t\tthis.setCurrentTime(this.timelineState.currentTime, true);\n\t};\n\tprivate onPageHide = () => {\n\t\tthis.isPageVisible = false;\n\t};\n\tprivate scrolledHandler: ReturnType<typeof setTimeout> | undefined;\n\t/** @internal */\n\tresizeObserver: ResizeObserver = new ResizeObserver(((entries) => {\n\t\tlet shouldRelayout = false;\n\t\tlet shouldRebuildPlayerStyle = false;\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.target === this.element) {\n\t\t\t\tconst rect = entry.contentRect;\n\t\t\t\tthis.size[0] = rect.width;\n\t\t\t\tthis.size[1] = rect.height;\n\t\t\t\tshouldRebuildPlayerStyle = true;\n\t\t\t} else if (entry.target === this.interludeDots.getElement()) {\n\t\t\t\tthis.layoutState.interludeDotsSize[0] = entry.target.clientWidth;\n\t\t\t\tthis.layoutState.interludeDotsSize[1] = entry.target.clientHeight;\n\t\t\t\tshouldRelayout = true;\n\t\t\t} else if (entry.target === this.bottomLine.getElement()) {\n\t\t\t\tconst newSize: [number, number] = [\n\t\t\t\t\tentry.target.clientWidth,\n\t\t\t\t\tentry.target.clientHeight,\n\t\t\t\t];\n\t\t\t\tconst oldSize: [number, number] = this.bottomLine.lineSize;\n\n\t\t\t\tif (newSize[0] !== oldSize[0] || newSize[1] !== oldSize[1]) {\n\t\t\t\t\tthis.bottomLine.lineSize = newSize;\n\t\t\t\t\tshouldRelayout = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst groupObj = this.lyricGroupElementMap.get(entry.target);\n\t\t\t\tif (groupObj) {\n\t\t\t\t\tconst newSize: [number, number] = [\n\t\t\t\t\t\tentry.target.clientWidth,\n\t\t\t\t\t\tentry.target.clientHeight,\n\t\t\t\t\t];\n\n\t\t\t\t\tconst oldSize: [number, number] = this.lyricGroupSize.get(\n\t\t\t\t\t\tgroupObj,\n\t\t\t\t\t) ?? [0, 0];\n\n\t\t\t\t\tif (newSize[0] !== oldSize[0] || newSize[1] !== oldSize[1]) {\n\t\t\t\t\t\tthis.lyricGroupSize.set(groupObj, newSize);\n\t\t\t\t\t\tgroupObj.onLineSizeChange(newSize);\n\t\t\t\t\t\tshouldRelayout = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (shouldRelayout) {\n\t\t\tthis.calcLayout(true);\n\t\t}\n\t\tif (shouldRebuildPlayerStyle) {\n\t\t\tthis.onResize();\n\t\t}\n\t}) as ResizeObserverCallback);\n\tprotected wordFadeWidth = 0.5;\n\n\tconstructor(element?: HTMLElement) {\n\t\tsuper();\n\t\tif (element) this.element = element;\n\t\tthis.element.classList.add(\"amll-lyric-player\");\n\n\t\tthis.resizeObserver.observe(this.element);\n\t\tthis.resizeObserver.observe(this.interludeDots.getElement());\n\n\t\tthis.element.appendChild(this.interludeDots.getElement());\n\t\tthis.element.appendChild(this.bottomLine.getElement());\n\t\tthis.interludeDots.setTransform(0, 200);\n\n\t\twindow.addEventListener(\"pageshow\", this.onPageShow);\n\t\twindow.addEventListener(\"pagehide\", this.onPageHide);\n\t\tattachPlayerScrollHandlers(this.element, this.scrollState, {\n\t\t\tonBeginScroll: () => this.beginScrollHandler(),\n\t\t\tonEndScroll: () => this.endScrollHandler(),\n\t\t\tonLayout: (sync, force) => this.calcLayout(sync, force),\n\t\t\tcontainsTarget: (target) => this.element.contains(target),\n\t\t\tclickTarget: (target) => target.click(),\n\t\t});\n\t}\n\n\tprivate beginScrollHandler() {\n\t\tconst allowed = this.scrollState.allowScroll;\n\t\tif (allowed) {\n\t\t\tthis.scrollState.isScrolled = true;\n\t\t\tclearTimeout(this.scrolledHandler);\n\t\t\tthis.scrolledHandler = setTimeout(() => {\n\t\t\t\tthis.scrollState.isScrolled = false;\n\t\t\t\tthis.scrollState.scrollOffset = 0;\n\t\t\t}, 5000);\n\t\t}\n\t\treturn allowed;\n\t}\n\tprivate endScrollHandler() {}\n\n\t/**\n\t * 设置文字动画的渐变宽度,单位以歌词行的主文字字体大小的倍数为单位,默认为 0.5,即一个全角字符的一半宽度\n\t *\n\t * 如果要模拟 Apple Music for Android 的效果,可以设置为 1\n\t *\n\t * 如果要模拟 Apple Music for iPad 的效果,可以设置为 0.5\n\t *\n\t * 如果想要近乎禁用渐变效果,可以设置成非常接近 0 的小数(例如 `0.0001` ),但是**不可以为 0**\n\t *\n\t * @param value 需要设置的渐变宽度,单位以歌词行的主文字字体大小的倍数为单位,默认为 0.5\n\t */\n\tsetWordFadeWidth(value = 0.5): void {\n\t\tthis.wordFadeWidth = Math.max(0.0001, value);\n\t}\n\n\t/**\n\t * 是否启用歌词行缩放效果,默认启用\n\t *\n\t * 如果启用,非选中的歌词行会轻微缩小以凸显当前播放歌词行效果\n\t *\n\t * 此效果对性能影响微乎其微,推荐启用\n\t * @param enable 是否启用歌词行缩放效果\n\t */\n\tsetEnableScale(enable = true): void {\n\t\tthis.enableScale = enable;\n\t\tthis.calcLayout();\n\t}\n\t/**\n\t * 获取当前是否启用了歌词行缩放效果\n\t * @returns 是否启用歌词行缩放效果\n\t */\n\tgetEnableScale(): boolean {\n\t\treturn this.enableScale;\n\t}\n\n\t/**\n\t * 获取当前文字动画的渐变宽度,单位以歌词行的主文字字体大小的倍数为单位\n\t * @returns 当前文字动画的渐变宽度,单位以歌词行的主文字字体大小的倍数为单位\n\t */\n\tgetWordFadeWidth(): number {\n\t\treturn this.wordFadeWidth;\n\t}\n\n\tsetIsSeeking(isSeeking: boolean): void {\n\t\tthis.timelineState.isSeeking = isSeeking;\n\t}\n\t/**\n\t * 设置是否隐藏已经播放过的歌词行,默认不隐藏\n\t * @param hide 是否隐藏已经播放过的歌词行,默认不隐藏\n\t */\n\tsetHidePassedLines(hide: boolean): void {\n\t\tthis.hidePassedLines = hide;\n\t\tthis.calcLayout();\n\t}\n\t/**\n\t * 设置是否启用歌词行的模糊效果\n\t * @param enable 是否启用\n\t */\n\tsetEnableBlur(enable: boolean): void {\n\t\tif (this.enableBlur === enable) return;\n\t\tthis.enableBlur = enable;\n\t\tthis.calcLayout();\n\t}\n\n\t/**\n\t * 设置歌词中不雅用语的掩码模式\n\t * @param mode 掩码模式\n\t * @see {@link MaskObsceneWordsMode}\n\t */\n\tsetMaskObsceneWords(mode: MaskObsceneWordsMode): void {\n\t\tif (this.maskObsceneWords === mode) return;\n\t\tthis.maskObsceneWords = mode;\n\t\tthis.rebuildLyricLines();\n\t\tthis.calcLayout();\n\t}\n\n\t/**\n\t * 设置不雅用语掩码使用的字符,默认为 `*`\n\t * @param char 单个字符,用于替换不雅用语中的字符\n\t */\n\tsetMaskObsceneWordChar(char: string): void {\n\t\tconst c = char.charAt(0) || \"*\";\n\t\tif (this.maskObsceneWordChar === c) return;\n\t\tthis.maskObsceneWordChar = c;\n\t\tif (this.maskObsceneWords !== MaskObsceneWordsMode.Disabled) {\n\t\t\tthis.rebuildLyricLines();\n\t\t\tthis.calcLayout();\n\t\t}\n\t}\n\n\trebuildLyricLines(): void {\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.rebuildAllLines();\n\t\t}\n\t}\n\t/**\n\t * 根据当前配置处理不雅用语单词\n\t * @param word 单词对象\n\t * @internal\n\t */\n\tprocessObsceneWord(word: LyricWord): string {\n\t\tconst text = word.word;\n\n\t\tif (\n\t\t\t!word.obscene ||\n\t\t\tthis.maskObsceneWords === MaskObsceneWordsMode.Disabled\n\t\t) {\n\t\t\treturn text;\n\t\t}\n\n\t\tconst maskChar = this.maskObsceneWordChar;\n\n\t\tif (this.maskObsceneWords === MaskObsceneWordsMode.FullMask) {\n\t\t\treturn text.replace(/\\S/g, maskChar);\n\t\t}\n\n\t\tif (this.maskObsceneWords === MaskObsceneWordsMode.PartialMask) {\n\t\t\tconst trimmed = text.trim();\n\n\t\t\tif (trimmed.length <= 2) {\n\t\t\t\treturn text.replace(/\\S/g, maskChar);\n\t\t\t}\n\n\t\t\tconst startPos = text.indexOf(trimmed);\n\t\t\tconst endPos = startPos + trimmed.length - 1;\n\n\t\t\treturn (\n\t\t\t\ttext.slice(0, startPos + 1) +\n\t\t\t\ttext.slice(startPos + 1, endPos).replace(/\\S/g, maskChar) +\n\t\t\t\ttext.slice(endPos)\n\t\t\t);\n\t\t}\n\n\t\treturn text;\n\t}\n\t/**\n\t * 设置目标歌词行的对齐方式,默认为 `center`\n\t *\n\t * - 设置成 `top` 的话将会向目标歌词行的顶部对齐\n\t * - 设置成 `bottom` 的话将会向目标歌词行的底部对齐\n\t * - 设置成 `center` 的话将会向目标歌词行的垂直中心对齐\n\t * @param alignAnchor 歌词行对齐方式,详情见函数说明\n\t */\n\tsetAlignAnchor(alignAnchor: LayoutAlignAnchor): void {\n\t\tthis.layoutState.alignAnchor = alignAnchor;\n\t}\n\t/**\n\t * 设置默认的歌词行对齐位置,相对于整个歌词播放组件的大小位置,默认为 `0.5`\n\t * @param alignPosition 一个 `[0.0-1.0]` 之间的任意数字,代表组件高度由上到下的比例位置\n\t */\n\tsetAlignPosition(alignPosition: number): void {\n\t\tthis.layoutState.alignPosition = alignPosition;\n\t}\n\n\t/**\n\t * 设置 overscan(视图上下额外缓冲渲染区)距离,单位:像素。\n\t * @param px 像素值,默认 300\n\t */\n\tsetOverscanPx(px: number): void {\n\t\tthis.layoutState.overscanPx = clampPositive(px | 0);\n\t}\n\t/** 获取当前 overscan 像素距离 */\n\tgetOverscanPx(): number {\n\t\treturn this.layoutState.overscanPx;\n\t}\n\t/**\n\t * 设置是否使用物理弹簧算法实现歌词动画效果,默认启用\n\t *\n\t * 如果启用,则会通过弹簧算法实时处理歌词位置,但是需要性能足够强劲的电脑方可流畅运行\n\t *\n\t * 如果不启用,则会回退到基于 `transition` 的过渡效果,对低性能的机器比较友好,但是效果会比较单一\n\t */\n\tsetEnableSpring(enable = true): void {\n\t\tthis.disableSpring = !enable;\n\t\tif (enable) {\n\t\t\tthis.element.classList.remove(styles.disableSpring);\n\t\t} else {\n\t\t\tthis.element.classList.add(styles.disableSpring);\n\t\t}\n\t\tthis.calcLayout(true);\n\t}\n\t/**\n\t * 获取当前是否启用了物理弹簧\n\t * @returns 是否启用物理弹簧\n\t */\n\tgetEnableSpring(): boolean {\n\t\treturn !this.disableSpring;\n\t}\n\n\t/**\n\t * 设置歌词的优化配置项,这些配置项默认全部开启\n\t *\n\t * 注意,如果在 `setLyricLines` 之后修改此配置,需要重新调用 `setLyricLines()` 才能对当前歌词生效\n\t * @param options 优化配置选项\n\t * @see {@link OptimizeLyricOptions}\n\t */\n\tsetOptimizeOptions(options: OptimizeLyricOptions): void {\n\t\tthis.optimizeOptions = { ...this.optimizeOptions, ...options };\n\t}\n\n\t/**\n\t * 设置当前播放歌词,要注意传入后这个数组内的信息不得修改,否则会发生错误\n\t * @param lines 歌词数组\n\t * @param initialTime 初始时间,默认为 0\n\t */\n\tsetLyricLines(lines: LyricLine[], initialTime = 0): void {\n\t\tif (import.meta.env.DEV) {\n\t\t\tconsole.log(\"设置歌词行\", lines, initialTime);\n\t\t}\n\n\t\tthis.timelineState.initialLayoutFinished = true;\n\t\tthis.timelineState.lastCurrentTime = initialTime;\n\t\tthis.timelineState.currentTime = initialTime;\n\n\t\tthis.currentLyricLines = structuredClone(lines);\n\t\tthis.processedLines = structuredClone(this.currentLyricLines);\n\t\toptimizeLyricLines(this.processedLines, this.optimizeOptions);\n\n\t\tthis.isNonDynamic = true;\n\t\tfor (const line of this.processedLines) {\n\t\t\tif (line.words.length > 1) {\n\t\t\t\tthis.isNonDynamic = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tthis.hasDuetLine = this.processedLines.some((line) => line.isDuet);\n\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.dispose();\n\t\t}\n\t\tthis.currentLyricGroups = [];\n\n\t\tthis.interludeDots.setInterlude(undefined);\n\t\tthis.timelineState.hotGroups.clear();\n\t\tthis.timelineState.bufferedGroups.clear();\n\n\t\tif (import.meta.env.DEV) {\n\t\t\tconsole.log(\"歌词处理完成\", this);\n\t\t}\n\t}\n\n\t/**\n\t * 获取当前是否在播放\n\t * @returns 当前是否在播放\n\t */\n\tpublic getIsPlaying(): boolean {\n\t\treturn this.timelineState.isPlaying;\n\t}\n\n\t/**\n\t * 设置当前播放进度,此时将会更新内部的歌词进度信息。\n\t *\n\t * 内部会根据调用间隔和播放进度自动决定如何滚动和显示歌词,所以这个的调用频率越快越准确越好。\n\t * 调用完成后,应每帧调用 {@link update} 方法来执行歌词动画效果。**此函数本身不会触发动画效果**。\n\t *\n\t * @param time 当前播放进度,单位为毫秒\n\t */\n\tsetCurrentTime(time: number, isSeek = false): void {\n\t\t// 歌词行为如下:\n\t\t// 如果当前仍有缓冲行的情况下加入新热行,则不会解除当前缓冲行,且也不会修改当前滚动位置\n\t\t// 如果当前所有缓冲行都将被删除且没有新热行加入,则删除所有缓冲行,且也不会修改当前滚动位置\n\t\t// 如果当前所有缓冲行都将被删除且有新热行加入,则删除所有缓冲行并加入新热行作为缓冲行,然后修改当前滚动位置\n\n\t\ttime = Math.round(time);\n\n\t\tconst { timelineState } = this;\n\t\ttimelineState.isSeeking = Boolean(isSeek);\n\t\ttimelineState.currentTime = time;\n\n\t\tif (!timelineState.initialLayoutFinished && !timelineState.isSeeking)\n\t\t\treturn;\n\n\t\tconst stateResult = computePlayerTimeState({\n\t\t\ttime,\n\t\t\tcurrentGroups: this.currentLyricGroups,\n\t\t\ttimelineState,\n\t\t});\n\n\t\tconst bottomEl = this.bottomLine.getElement();\n\t\tconst hasBottomContent = bottomEl.innerHTML.trim().length > 0;\n\t\tconst commitResult = commitPlayerTimeState({\n\t\t\ttimelineState: timelineState,\n\t\t\ttime,\n\t\t\tcurrentGroups: this.currentLyricGroups,\n\t\t\thasBottomContent,\n\t\t\tstateResult,\n\t\t});\n\n\t\tfor (const id of commitResult.groupsToDisable)\n\t\t\tthis.currentLyricGroups[id]?.disable();\n\n\t\tfor (const id of commitResult.groupsToEnable)\n\t\t\tthis.currentLyricGroups[id]?.enable();\n\n\t\tif (commitResult.shouldResetScroll) this.resetScroll();\n\t\tif (commitResult.shouldLayout) this.calcLayout();\n\t}\n\n\t/**\n\t * 重新布局定位歌词行的位置,调用完成后再逐帧调用 `update`\n\t * 函数即可让歌词通过动画移动到目标位置。\n\t *\n\t * 函数有一个 `force` 参数,用于指定是否强制修改布局,也就是不经过动画直接调整元素位置和大小。\n\t *\n\t * 此函数还有一个 `reflow` 参数,用于指定是否需要重新计算布局\n\t *\n\t * 因为计算布局必定会导致浏览器重排布局,所以会大幅度影响流畅度和性能,故请只在以下情况下将其​设置为 true:\n\t *\n\t * 1. 歌词页面大小发生改变时(这个组件会自行处理)\n\t * 2. 加载了新的歌词时(不论前后歌词是否完全一样)\n\t * 3. 用户自行跳转了歌曲播放位置(不论距离远近)\n\t *\n\t * @param sync 是否同步执行,通常用于初始化或 Resize 时立即布局\n\t * @param force 是否绕过弹簧效果强制更新位置\n\t */\n\tasync calcLayout(sync = false, force = false): Promise<void> {\n\t\tconst interlude = computeCurrentInterlude({\n\t\t\tcurrentTime: this.timelineState.currentTime,\n\t\t\tscrollToIndex: this.timelineState.scrollToIndex,\n\t\t\tcurrentGroups: this.currentLyricGroups,\n\t\t});\n\t\tconst isInterludeActive = !!interlude;\n\n\t\tif (\n\t\t\tthis.layoutState.targetAlignIndex !== this.timelineState.scrollToIndex ||\n\t\t\tthis.layoutState.lastInterludeState !== isInterludeActive\n\t\t) {\n\t\t\tthis.layoutState.lastInterludeState = isInterludeActive;\n\n\t\t\tconst springParams = computeLinePosYSpringParams({\n\t\t\t\tenabled: this.getEnableSpring(),\n\t\t\t\tcurrentGroups: this.currentLyricGroups,\n\t\t\t\tscrollToIndex: this.timelineState.scrollToIndex,\n\t\t\t\tisSeeking: this.timelineState.isSeeking,\n\t\t\t\tisInterludeActive,\n\t\t\t});\n\t\t\tif (springParams.shouldUpdate && springParams.params) {\n\t\t\t\tthis.setLinePosYSpringParams(springParams.params);\n\t\t\t}\n\t\t}\n\n\t\tlet curPos = -this.scrollState.scrollOffset;\n\t\tconst targetAlignIndex = this.timelineState.scrollToIndex;\n\t\tlet isNextDuet = false;\n\t\tif (interlude) {\n\t\t\tisNextDuet = interlude.isNextDuet;\n\t\t} else {\n\t\t\tthis.interludeDots.setInterlude(undefined);\n\t\t}\n\n\t\tconst fontSize = this.baseFontSize || 24;\n\t\tconst dotMargin = fontSize * 0.4;\n\t\tconst totalInterludeHeight =\n\t\t\tthis.layoutState.interludeDotsSize[1] + dotMargin * 2;\n\n\t\tif (interlude) {\n\t\t\tif (interlude.anchorLineIndex !== -1) {\n\t\t\t\tcurPos -= totalInterludeHeight;\n\t\t\t}\n\t\t}\n\t\t// 避免一开始就让所有歌词行挤在一起\n\t\tconst LINE_HEIGHT_FALLBACK = this.size[1] / 5;\n\t\tconst scrollOffset = this.currentLyricGroups\n\t\t\t.slice(0, targetAlignIndex)\n\t\t\t.reduce(\n\t\t\t\t(acc, group) =>\n\t\t\t\t\tacc + (this.lyricGroupSize.get(group)?.[1] ?? LINE_HEIGHT_FALLBACK),\n\t\t\t\t0,\n\t\t\t);\n\n\t\tthis.scrollState.scrollBoundary.minOffset = -scrollOffset;\n\t\tcurPos -= scrollOffset;\n\t\tcurPos += this.size[1] * this.layoutState.alignPosition;\n\n\t\tconst curGroup = this.currentLyricGroups[targetAlignIndex];\n\t\tthis.layoutState.targetAlignIndex = targetAlignIndex;\n\n\t\tconst isBottomFocused = targetAlignIndex === this.currentLyricGroups.length;\n\t\tthis.bottomLine.setFocused(isBottomFocused);\n\n\t\tconst targetLineHeight = curGroup\n\t\t\t? (this.lyricGroupSize.get(curGroup)?.[1] ?? LINE_HEIGHT_FALLBACK)\n\t\t\t: isBottomFocused\n\t\t\t\t? this.bottomLine.lineSize[1]\n\t\t\t\t: 0;\n\n\t\tif (targetLineHeight > 0) {\n\t\t\tswitch (this.layoutState.alignAnchor) {\n\t\t\t\tcase LayoutAlignAnchor.Bottom:\n\t\t\t\t\tcurPos -= targetLineHeight;\n\t\t\t\t\tbreak;\n\t\t\t\tcase LayoutAlignAnchor.Center:\n\t\t\t\t\tcurPos -= targetLineHeight / 2;\n\t\t\t\t\tbreak;\n\t\t\t\tcase LayoutAlignAnchor.Top:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tconst latestIndex = Math.max(...this.timelineState.bufferedGroups);\n\t\tlet delay = 0;\n\t\tlet baseDelay = sync ? 0 : 0.05;\n\t\tlet setDots = false;\n\n\t\tthis.currentLyricGroups.forEach((group, i) => {\n\t\t\tconst hasBuffered = this.timelineState.bufferedGroups.has(i);\n\n\t\t\tconst shouldShowDots = interlude && i === interlude.anchorLineIndex + 1;\n\n\t\t\tif (!setDots && shouldShowDots) {\n\t\t\t\tsetDots = true;\n\n\t\t\t\tcurPos += dotMargin;\n\n\t\t\t\tlet targetX = 0;\n\t\t\t\tif (interlude && isNextDuet) {\n\t\t\t\t\ttargetX = this.size[0] - this.layoutState.interludeDotsSize[0];\n\t\t\t\t}\n\n\t\t\t\tthis.interludeDots.setTransform(targetX, curPos);\n\n\t\t\t\tif (interlude) {\n\t\t\t\t\tthis.interludeDots.setInterlude([\n\t\t\t\t\t\tinterlude.startTime,\n\t\t\t\t\t\tinterlude.endTime,\n\t\t\t\t\t]);\n\t\t\t\t}\n\t\t\t\tcurPos += this.layoutState.interludeDotsSize[1];\n\t\t\t\tcurPos += dotMargin;\n\t\t\t}\n\n\t\t\tconst presentation = computeGroupPresentation({\n\t\t\t\tgroupIndex: i,\n\t\t\t\tscrollToIndex: this.timelineState.scrollToIndex,\n\t\t\t\tlatestIndex,\n\t\t\t\thasBuffered,\n\t\t\t\thidePassedLines: this.hidePassedLines,\n\t\t\t\tisPlaying: this.timelineState.isPlaying,\n\t\t\t\tisNonDynamic: this.isNonDynamic,\n\t\t\t\tenableBlur: this.enableBlur,\n\t\t\t\tisUserScrolling: this.scrollState.isUserScrolling,\n\t\t\t\tisCompact: window.innerWidth <= 1024,\n\t\t\t\tinterlude,\n\t\t\t});\n\n\t\t\tgroup.setTransform(\n\t\t\t\tcurPos,\n\t\t\t\tforce,\n\t\t\t\tdelay,\n\t\t\t\tpresentation.isActive,\n\t\t\t\tpresentation.targetOpacity,\n\t\t\t\tpresentation.blurLevel,\n\t\t\t);\n\n\t\t\tcurPos += this.lyricGroupSize.get(group)?.[1] ?? LINE_HEIGHT_FALLBACK;\n\n\t\t\tif (curPos >= 0 && !this.timelineState.isSeeking) {\n\t\t\t\tdelay += baseDelay;\n\t\t\t\tif (i >= this.timelineState.scrollToIndex) baseDelay /= 1.05;\n\t\t\t}\n\t\t});\n\t\tthis.scrollState.scrollBoundary.maxOffset =\n\t\t\tcurPos + this.scrollState.scrollOffset - this.size[1] / 2;\n\n\t\tconst bottomIndex = this.currentLyricGroups.length;\n\t\tconst finalBottomBlur = computeLineBlur({\n\t\t\tenableBlur: this.enableBlur,\n\t\t\tisUserScrolling: this.scrollState.isUserScrolling,\n\t\t\tisActive: isBottomFocused,\n\t\t\titemIndex: bottomIndex,\n\t\t\tscrollToIndex: this.timelineState.scrollToIndex,\n\t\t\tlatestIndex,\n\t\t\tisCompact: window.innerWidth <= 1024,\n\t\t});\n\n\t\tthis.bottomLine.setTransform(0, curPos, finalBottomBlur, force, delay);\n\t}\n\n\t/**\n\t * 设置所有歌词行在横坐标上的弹簧属性,包括重量、弹力和阻力。\n\t *\n\t * @param params 需要设置的弹簧属性,提供的属性将会覆盖原来的属性,未提供的属性将会保持原样\n\t * @deprecated 考虑到横向弹簧效果并不常见,所以这个函数将会在未来的版本中移除\n\t */\n\tsetLinePosXSpringParams(_params: Partial<SpringParams> = {}): void {}\n\t/**\n\t * 设置所有歌词行在​纵坐标上的弹簧属性,包括重量、弹力和阻力。\n\t *\n\t * @param params 需要设置的弹簧属性,提供的属性将会覆盖原来的属性,未提供的属性将会保持原样\n\t */\n\tsetLinePosYSpringParams(params: Partial<SpringParams> = {}): void {\n\t\tthis.posYSpringParams = {\n\t\t\t...this.posYSpringParams,\n\t\t\t...params,\n\t\t};\n\t\tthis.bottomLine.lineTransforms.posY.updateParams(this.posYSpringParams);\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.posY.updateParams(this.posYSpringParams);\n\t\t\tgroup.bgSlideY.updateParams(this.posYSpringParams);\n\t\t}\n\t}\n\t/**\n\t * 设置所有歌词行在​缩放大小上的弹簧属性,包括重量、弹力和阻力。\n\t *\n\t * @param params 需要设置的弹簧属性,提供的属性将会覆盖原来的属性,未提供的属性将会保持原样\n\t */\n\tsetLineScaleSpringParams(params: Partial<SpringParams> = {}): void {\n\t\tthis.scaleSpringParams = {\n\t\t\t...this.scaleSpringParams,\n\t\t\t...params,\n\t\t};\n\t\tthis.scaleForBGSpringParams = {\n\t\t\t...this.scaleForBGSpringParams,\n\t\t\t...params,\n\t\t};\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.mainLine.lineTransforms.scale.updateParams(this.scaleSpringParams);\n\n\t\t\tgroup.bgLine?.lineTransforms.scale.updateParams(\n\t\t\t\tthis.scaleForBGSpringParams,\n\t\t\t);\n\t\t}\n\t}\n\t/**\n\t * 暂停部分效果演出,目前会暂停播放间奏点的动画,且将背景歌词显示出来\n\t */\n\tpause(): void {\n\t\tthis.interludeDots.pause();\n\t\tif (this.timelineState.isPlaying) {\n\t\t\tthis.timelineState.isPlaying = false;\n\t\t\tthis.calcLayout();\n\t\t}\n\t}\n\t/**\n\t * 恢复部分效果演出,目前会恢复播放间奏点的动画\n\t */\n\tresume(): void {\n\t\tthis.interludeDots.resume();\n\t\tif (!this.timelineState.isPlaying) {\n\t\t\tthis.timelineState.isPlaying = true;\n\t\t\tthis.calcLayout();\n\t\t}\n\t}\n\t/**\n\t * 更新动画,这个函数应该被逐帧调用或者在以下情况下调用一次:\n\t *\n\t * 1. 刚刚调用完设置歌词函数的时候\n\t * @param delta 距离上一次被调用到现在的时长,单位为毫秒(可为浮点数)\n\t */\n\n\tupdate(delta = 0): void {\n\t\tthis.bottomLine.update(delta / 1000);\n\t\tthis.interludeDots.update(delta);\n\t}\n\n\tprotected onResize(): void {}\n\n\t/**\n\t * 获取一个特殊的底栏元素,默认是空白的,可以往内部添加任意元素\n\t *\n\t * 这个元素始终在歌词的底部,可以用于显示歌曲创作者等信息\n\t *\n\t * 但是请勿删除该元素,只能在内部存放元素\n\t *\n\t * @returns 一个元素,可以往内部添加任意元素\n\t */\n\tgetBottomLineElement(): HTMLElement {\n\t\treturn this.bottomLine.getElement();\n\t}\n\t/**\n\t * 重置用户滚动状态\n\t *\n\t * 请在用户完成滚动点击跳转歌词时调用本事件再调用 `calcLayout` 以正确滚动到目标位置\n\t */\n\tresetScroll(): void {\n\t\tresetPlayerScrollState(this.scrollState);\n\t\tclearTimeout(this.scrolledHandler);\n\t}\n\t/**\n\t * 获取当前歌词数组\n\t *\n\t * 一般和最后调用 `setLyricLines` 给予的参数一样\n\t * @returns 当前歌词数组\n\t */\n\tgetLyricLines(): LyricLine[] {\n\t\treturn this.currentLyricLines;\n\t}\n\t/**\n\t * 获取当前歌词的播放位置\n\t *\n\t * 一般和最后调用 `setCurrentTime` 给予的参数一样\n\t * @returns 当前播放位置\n\t */\n\tgetCurrentTime(): number {\n\t\treturn this.timelineState.currentTime;\n\t}\n\n\t/**\n\t * 设置是否让背景人声行始终后置显示\n\t *\n\t * 默认情况下,如果背景歌词开始时间早于主歌词,会在主歌词上方展示;\n\t * 如果设置为 `true`,则无论时间顺序如何,背景歌词都会始终在主歌词下方展示\n\t * @param enable 是否启用始终后置\n\t */\n\tsetAlwaysPostpositionBackground(enable: boolean): void {\n\t\tif (this.alwaysPostpositionBackground === enable) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.alwaysPostpositionBackground = enable;\n\n\t\tthis.rebuildLyricLines();\n\t\tthis.calcLayout();\n\t}\n\n\t/** 获取当前是否设置了让背景人声行始终后置显示 */\n\tgetAlwaysPostpositionBackground(): boolean {\n\t\treturn this.alwaysPostpositionBackground;\n\t}\n\n\tgetElement(): HTMLElement {\n\t\treturn this.element;\n\t}\n\tdispose(): void {\n\t\tthis.element.remove();\n\t\twindow.removeEventListener(\"pageshow\", this.onPageShow);\n\t\twindow.removeEventListener(\"pagehide\", this.onPageHide);\n\t}\n}\n","import type { Disposable } from \"#interfaces\";\nimport { Spring } from \"#utils/spring.ts\";\nimport { LyricLineRenderMode } from \"./consts.ts\";\nimport type { LyricLineBase } from \"./line.ts\";\n\nexport interface LyricPlayerFlags {\n\tgetEnableSpring(): boolean;\n\tgetEnableScale(): boolean;\n\tgetIsPlaying(): boolean;\n\tgetAlwaysPostpositionBackground(): boolean;\n}\n\nexport abstract class LyricLineGroupBase<\n\tT extends LyricLineBase = LyricLineBase,\n> implements Disposable\n{\n\tprotected abstract readonly lyricPlayer: LyricPlayerFlags;\n\n\tpublic posY: Spring = new Spring(0);\n\tpublic bgSlideY: Spring = new Spring(-80);\n\tpublic top = 0;\n\tpublic delay = 0;\n\n\tpublic isActive = false;\n\tpublic opacity = 1;\n\tpublic blur = 0;\n\n\tpublic isBgFirst = false;\n\n\tconstructor(\n\t\tpublic mainLine: T,\n\t\tpublic bgLine?: T | undefined,\n\t) {}\n\n\tget startTime(): number {\n\t\t// 优化歌词时 `syncMainAndBackgroundLines` 已经把时间同步好了,直接读取主歌词的即可\n\t\t// 要是用户关掉了这个优化,我们认为在这种情况下主歌词和背景人声显示不同步是符合用户预期的\n\t\treturn this.mainLine.getLine().startTime;\n\t}\n\n\tget endTime(): number {\n\t\treturn this.mainLine.getLine().endTime;\n\t}\n\n\tonLineSizeChange(size: [number, number]): void {\n\t\tthis.mainLine.onLineSizeChange(size);\n\t\tthis.bgLine?.onLineSizeChange(size);\n\t}\n\n\tsetTransform(\n\t\ttop: number,\n\t\tforce: boolean,\n\t\tdelay: number,\n\t\tisActive: boolean,\n\t\topacity: number,\n\t\tblur: number,\n\t): void {\n\t\tthis.top = top;\n\t\tthis.delay = delay;\n\t\tthis.isActive = isActive;\n\t\tthis.opacity = opacity;\n\t\tthis.blur = blur;\n\n\t\tthis.setLineTransformations(force, delay);\n\n\t\tconst enableSpring = this.lyricPlayer.getEnableSpring();\n\t\tconst alwaysPostposition =\n\t\t\tthis.lyricPlayer.getAlwaysPostpositionBackground();\n\t\tconst shouldBgFirst = alwaysPostposition ? false : this.isBgFirst;\n\t\tconst hiddenSlideY = shouldBgFirst ? 80 : -80;\n\n\t\tconst isPlaying = this.lyricPlayer.getIsPlaying();\n\n\t\tconst targetBgSlideY = isActive || !isPlaying ? 0 : hiddenSlideY;\n\n\t\tif (force || !enableSpring) {\n\t\t\tthis.posY.setPosition(top);\n\t\t\tthis.bgSlideY.setPosition(targetBgSlideY);\n\t\t\tthis.renderStyles();\n\t\t} else {\n\t\t\tthis.posY.setTargetPosition(top, delay);\n\t\t\tthis.bgSlideY.setTargetPosition(targetBgSlideY, delay);\n\t\t}\n\t}\n\n\tprivate setLineTransformations(force: boolean, delay: number) {\n\t\tconst enableScale = this.lyricPlayer.getEnableScale();\n\t\tconst isPlaying = this.lyricPlayer.getIsPlaying();\n\n\t\tconst renderMode = this.isActive\n\t\t\t? LyricLineRenderMode.GRADIENT\n\t\t\t: LyricLineRenderMode.SOLID;\n\n\t\tconst SCALE_ASPECT = enableScale ? 97 : 100;\n\t\tlet mainScale = 100;\n\t\tif (!this.isActive && isPlaying) {\n\t\t\tmainScale = SCALE_ASPECT;\n\t\t}\n\t\tthis.mainLine.setTransform(mainScale, 1, 0, force, delay, renderMode);\n\n\t\tlet bgScale = 100;\n\t\tif (!this.isActive && isPlaying) {\n\t\t\tbgScale = 75;\n\t\t}\n\t\tthis.bgLine?.setTransform(bgScale, 1, 0, force, delay, renderMode);\n\t}\n\n\tprotected abstract renderStyles(): void;\n\n\tabstract get isInSight(): boolean;\n\n\tupdate(delta: number): void {\n\t\tif (this.lyricPlayer.getEnableSpring()) {\n\t\t\tthis.posY.update(delta);\n\t\t\tthis.bgSlideY.update(delta);\n\t\t\tthis.renderStyles();\n\t\t}\n\n\t\tthis.mainLine.update(delta);\n\t\tthis.bgLine?.update(delta);\n\t}\n\n\trebuildAllLines(): void {\n\t\tthis.mainLine.rebuildElement();\n\t\tthis.bgLine?.rebuildElement();\n\t}\n\n\tenable(time?: number, shouldPlay?: boolean): void {\n\t\tthis.mainLine.enable(time, shouldPlay);\n\t\tthis.bgLine?.enable(time, shouldPlay);\n\t}\n\n\tdisable(): void {\n\t\tthis.mainLine.disable();\n\t\tthis.bgLine?.disable();\n\t}\n\n\tdispose(): void {\n\t\tthis.mainLine.dispose();\n\t\tthis.bgLine?.dispose();\n\t}\n}\n","import { LyricLineGroupBase } from \"#lyric/base/group.ts\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { clamp01 } from \"#utils/clamp.ts\";\nimport type { DomLyricPlayer } from \"./index.ts\";\nimport type { LyricLineEl } from \"./lyric-line.ts\";\n\nexport class LyricLineGroup extends LyricLineGroupBase<LyricLineEl> {\n\tpublic element: HTMLElement;\n\tpublic bgWrapper?: HTMLElement;\n\tprivate lastIsActive?: boolean;\n\n\tconstructor(\n\t\tpublic lyricPlayer: DomLyricPlayer,\n\t\tmainLine: LyricLineEl,\n\t) {\n\t\tsuper(mainLine);\n\t\tthis.element = document.createElement(\"div\");\n\t\tthis.element.className = styles.lyricLineWrapper;\n\t\tthis.element.appendChild(mainLine.getElement());\n\t\tthis.posY.setPosition(window.innerHeight * 2);\n\n\t\tlyricPlayer.resizeObserver.observe(this.element);\n\t}\n\n\tget isInSight(): boolean {\n\t\tconst t = this.posY.getCurrentPosition();\n\n\t\tlet h = this.lyricPlayer.lyricGroupSize?.get(this)?.[1];\n\t\tif (h === undefined || h === 0) {\n\t\t\th = this.element.clientHeight || 0;\n\t\t}\n\n\t\tconst pb = this.lyricPlayer.size[1];\n\t\tconst ov = this.lyricPlayer.getOverscanPx();\n\n\t\treturn !(t > pb + h + ov || t < -h - ov);\n\t}\n\n\tshow(): void {\n\t\tif (!this.element.parentElement) {\n\t\t\tconst playerEl = this.lyricPlayer.getElement();\n\t\t\tconst groups = this.lyricPlayer.currentLyricGroups;\n\t\t\tconst myIndex = groups.indexOf(this);\n\n\t\t\tlet referenceNode: HTMLElement | null = null;\n\t\t\tif (myIndex !== -1) {\n\t\t\t\tfor (let i = myIndex + 1; i < groups.length; i++) {\n\t\t\t\t\tif (groups[i].element.parentElement === playerEl) {\n\t\t\t\t\t\treferenceNode = groups[i].element;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tplayerEl.insertBefore(this.element, referenceNode);\n\n\t\t\tthis.lyricPlayer.resizeObserver.observe(this.element);\n\t\t}\n\n\t\tthis.mainLine.show();\n\t\tthis.bgLine?.show();\n\t}\n\n\thide(): void {\n\t\tif (this.element.parentElement) {\n\t\t\tthis.lyricPlayer.resizeObserver.unobserve(this.element);\n\t\t\tthis.element.remove();\n\n\t\t\tthis.mainLine.teardownContent();\n\t\t\tthis.bgLine?.teardownContent();\n\t\t}\n\t}\n\n\toverride update(delta: number): void {\n\t\tif (this.isInSight) {\n\t\t\tthis.show();\n\t\t} else {\n\t\t\tthis.hide();\n\t\t}\n\n\t\tsuper.update(delta);\n\t}\n\n\taddBgLine(bgLine: LyricLineEl): void {\n\t\tif (this.bgLine) {\n\t\t\tthis.bgLine.dispose();\n\t\t}\n\t\tif (this.bgWrapper) {\n\t\t\tthis.bgWrapper.remove();\n\t\t}\n\n\t\tthis.bgLine = bgLine;\n\n\t\t// 需要对比第一个词的开始时间而不是行起始时间,因为行的起始时间已经被\n\t\t// `syncMainAndBackgroundLines` 同步过了\n\t\tconst bgStartTime =\n\t\t\tbgLine.getLine().words[0]?.startTime ?? bgLine.getLine().startTime;\n\t\tconst mainStartTime =\n\t\t\tthis.mainLine.getLine().words[0]?.startTime ??\n\t\t\tthis.mainLine.getLine().startTime;\n\n\t\tthis.isBgFirst = bgStartTime < mainStartTime;\n\n\t\tif (this.mainLine.getLine().isDuet) {\n\t\t\tbgLine.getElement().classList.add(styles.lyricDuetLine);\n\t\t}\n\n\t\tthis.bgWrapper = document.createElement(\"div\");\n\t\tthis.bgWrapper.className = styles.bgWrapper;\n\n\t\tthis.bgWrapper.appendChild(bgLine.getElement());\n\n\t\tconst alwaysPostposition =\n\t\t\tthis.lyricPlayer.getAlwaysPostpositionBackground();\n\t\tconst shouldBgFirst = !alwaysPostposition && this.isBgFirst;\n\n\t\tif (shouldBgFirst) {\n\t\t\tthis.bgWrapper.classList.add(styles.bgWrapperTop);\n\t\t\tthis.element.insertBefore(this.bgWrapper, this.mainLine.getElement());\n\t\t\tthis.bgSlideY.setPosition(80);\n\t\t} else {\n\t\t\tthis.element.appendChild(this.bgWrapper);\n\t\t}\n\t}\n\n\tprotected renderStyles(): void {\n\t\tconst y = this.posY.getCurrentPosition().toFixed(1);\n\n\t\tthis.element.style.transform = `translateY(${y}px)`;\n\t\tthis.element.style.opacity = this.opacity.toString();\n\t\tthis.element.style.filter = `blur(${Math.min(5, this.blur)}px)`;\n\n\t\tif (!this.lyricPlayer.getEnableSpring()) {\n\t\t\tthis.element.style.transitionDelay = `${this.delay}ms`;\n\t\t}\n\n\t\tif (this.bgWrapper) {\n\t\t\tif (this.lastIsActive !== this.isActive) {\n\t\t\t\tthis.lastIsActive = this.isActive;\n\t\t\t\tthis.bgWrapper.classList.toggle(styles.bgWrapperActive, this.isActive);\n\t\t\t}\n\n\t\t\tconst slideY = this.bgSlideY.getCurrentPosition();\n\t\t\tconst slideYStr = slideY.toFixed(1);\n\t\t\tconst activeProgress = clamp01(1 - Math.abs(slideY) / 80);\n\n\t\t\tconst scaleStr = (0.8 + activeProgress * 0.2).toFixed(3);\n\t\t\tthis.bgWrapper.style.transform = `translateY(${slideYStr}%) scale(${scaleStr})`;\n\n\t\t\tconst alwaysPostposition =\n\t\t\t\tthis.lyricPlayer.getAlwaysPostpositionBackground();\n\t\t\tconst shouldBgFirst = !alwaysPostposition && this.isBgFirst;\n\n\t\t\tif (shouldBgFirst) {\n\t\t\t\tconst bgHeight = this.bgWrapper.clientHeight || 0;\n\t\t\t\tconst currentMarginTop = -bgHeight * (1 - activeProgress);\n\t\t\t\tthis.bgWrapper.style.marginTop = `${currentMarginTop.toFixed(1)}px`;\n\t\t\t} else {\n\t\t\t\tthis.bgWrapper.style.marginTop = \"\";\n\t\t\t}\n\n\t\t\tconst targetHiddenYStr = shouldBgFirst ? \"80.0\" : \"-80.0\";\n\t\t\tconst isHidden = slideYStr === targetHiddenYStr && !this.isActive;\n\t\t\tthis.bgWrapper.classList.toggle(styles.bgWrapperHidden, isHidden);\n\t\t}\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tthis.lyricPlayer.resizeObserver.unobserve(this.element);\n\t\tthis.element.remove();\n\t}\n}\n","export const isCJK = (char: string): boolean => {\n\treturn /^[\\p{Unified_Ideograph}\\u0800-\\u9FFC]+$/u.test(char);\n};\n","import type { Disposable, LyricLine, LyricWord } from \"#interfaces\";\nimport { isCJK } from \"#utils/is-cjk.ts\";\nimport { Spring } from \"#utils/spring.ts\";\nimport { LyricLineRenderMode } from \"./consts.ts\";\n\ninterface LineTransforms {\n\tscale: Spring;\n}\n\n/**\n * 所有标准歌词行的基类\n * @internal\n */\nexport abstract class LyricLineBase extends EventTarget implements Disposable {\n\tprotected top = 0;\n\tprotected scale = 1;\n\tprotected blur = 0;\n\tprotected opacity = 1;\n\tprotected delay = 0;\n\treadonly lineTransforms: LineTransforms = {\n\t\tscale: new Spring(100),\n\t};\n\n\t/**\n\t * 用于 CJK 词语边界检测的分词器\n\t */\n\tstatic readonly wordSegmenter: Intl.Segmenter | null =\n\t\ttypeof Intl !== \"undefined\" && Intl.Segmenter\n\t\t\t? new Intl.Segmenter(undefined, { granularity: \"word\" })\n\t\t\t: null;\n\n\t/**\n\t * Unicode 标准的全局 Grapheme Cluster 分词器\n\t * 用于正确处理 emoji、复合字符等\n\t */\n\tstatic readonly graphemeSegmenter: Intl.Segmenter | null =\n\t\ttypeof Intl !== \"undefined\" && Intl.Segmenter\n\t\t\t? new Intl.Segmenter(undefined, { granularity: \"grapheme\" })\n\t\t\t: null;\n\n\tabstract getLine(): LyricLine;\n\tabstract enable(time?: number, shouldPlay?: boolean): void;\n\tabstract disable(): void;\n\tabstract resume(): void;\n\tabstract pause(): void;\n\tabstract onLineSizeChange(size: [number, number]): void;\n\n\tsetTransform(\n\t\tscale: number = this.scale,\n\t\topacity: number = this.opacity,\n\t\tblur: number = this.blur,\n\t\t_force = false,\n\t\tdelay = 0,\n\t\t_mode: LyricLineRenderMode = LyricLineRenderMode.SOLID,\n\t): void {\n\t\tthis.scale = scale;\n\t\tthis.opacity = opacity;\n\t\tthis.blur = blur;\n\t\tthis.delay = delay;\n\t}\n\n\trebuildElement(): void {}\n\n\t/**\n\t * 判定歌词是否可以应用强调辉光效果\n\t *\n\t * 果子在对辉光效果的解释是一种强调(emphasized)效果\n\t *\n\t * 条件是一个单词时长大于等于 1s 且长度小于等于 7\n\t *\n\t * @param word 单词\n\t * @returns 是否可以应用强调辉光效果\n\t */\n\tstatic shouldEmphasize(word: LyricWord): boolean {\n\t\tif (isCJK(word.word)) return word.endTime - word.startTime >= 1000;\n\n\t\treturn (\n\t\t\tword.endTime - word.startTime >= 1000 &&\n\t\t\tword.word.trim().length <= 7 &&\n\t\t\tword.word.trim().length > 1\n\t\t);\n\t}\n\tabstract update(delta?: number): void;\n\tdispose(): void {}\n}\n","import { isCJK } from \"./is-cjk.ts\";\n\nexport interface ChildNodeInfo {\n\twidth: number;\n\ttext: string;\n\tisSpace: boolean;\n}\n\n/**\n * 单个词超过容器宽度时的大惩罚倍数\n */\nconst OVERFLOW_PENALTY_MULTIPLIER = 1000;\n/**\n * 截断 CJK 词组边界的惩罚比例\n *\n * 相对于容器宽度\n */\nconst CJK_BREAK_PENALTY_RATIO = 0.15;\n/**\n * 截断普通文本(非空格、非 CJK 词界)的惩罚比例\n */\nconst NORMAL_BREAK_PENALTY_RATIO = 0.5;\n/**\n * 在空格处断开的奖励比例\n */\nconst SPACE_BREAK_REWARD_RATIO = 0.4;\n/**\n * 在标点符号处断开的奖励比例\n *\n * 比空格更高以便优先一点在标点处换行\n */\nconst PUNCTUATION_BREAK_REWARD_RATIO = 0.6;\nconst PUNCTUATION_REGEX = /[,.;:!?,。;:!?、)】》」』’”)[\\]}>~…]$/;\n\n/**\n * 计算平均行长度的断点位置\n * @param children 子节点信息\n * @param containerWidth 容器可用内容宽度\n * @param fullText 完整的行文本\n * @param segmenter 预创建的 Intl.Segmenter 分词器\n * @returns 需要在其前面插入 `<br>` 的子节点索引数组,升序\n */\nexport function calcBalancedBreaks(\n\tchildren: ChildNodeInfo[],\n\tcontainerWidth: number,\n\tfullText: string,\n\tsegmenter: Intl.Segmenter,\n): number[] {\n\tconst n = children.length;\n\tif (n === 0 || containerWidth <= 0) {\n\t\treturn [];\n\t}\n\n\t// 计算哪里是 CJK 词组的边界\n\tconst cjkBoundaries = new Set<number>();\n\tlet offset = 0;\n\tfor (const { segment, isWordLike } of segmenter.segment(fullText)) {\n\t\tif (offset > 0 && isWordLike) {\n\t\t\tif ([...segment].some((ch) => isCJK(ch))) {\n\t\t\t\tcjkBoundaries.add(offset);\n\t\t\t}\n\t\t}\n\t\toffset += segment.length;\n\t}\n\n\t// 计算前缀宽和字符偏移量用于快速查询\n\tconst charOffsets = new Int32Array(n + 1);\n\tconst prefixWidth = new Float64Array(n + 1);\n\tfor (let i = 0; i < n; i++) {\n\t\tcharOffsets[i + 1] = charOffsets[i] + children[i].text.length;\n\t\tprefixWidth[i + 1] = prefixWidth[i] + children[i].width;\n\t}\n\n\tif (prefixWidth[n] <= containerWidth) {\n\t\treturn [];\n\t}\n\n\t/**\n\t * dp[i] 表示将 index i 到 n-1 的节点进行排版的最小代价\n\t */\n\tconst dp = new Float64Array(n + 1).fill(Number.POSITIVE_INFINITY);\n\tconst nextBreak = new Int32Array(n + 1).fill(-1);\n\tdp[n] = 0;\n\n\tconst PENALTY_CJK = (containerWidth * CJK_BREAK_PENALTY_RATIO) ** 2;\n\tconst PENALTY_NORMAL = (containerWidth * NORMAL_BREAK_PENALTY_RATIO) ** 2;\n\n\tfor (let i = n - 1; i >= 0; i--) {\n\t\tfor (let j = i + 1; j <= n; j++) {\n\t\t\tconst w = prefixWidth[j] - prefixWidth[i];\n\n\t\t\tlet lineCost = 0;\n\n\t\t\tif (w > containerWidth) {\n\t\t\t\tif (j === i + 1) {\n\t\t\t\t\t// 单个无法分割的词自身就比容器宽,被迫独立成行,给大惩罚\n\t\t\t\t\tlineCost = (w - containerWidth) ** 2 * OVERFLOW_PENALTY_MULTIPLIER;\n\t\t\t\t} else {\n\t\t\t\t\t// 行内包含多个超过物理宽度的词就跳过\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// 迫使所有行的长度方差最小化\n\t\t\t\tlineCost = (containerWidth - w) ** 2;\n\t\t\t}\n\n\t\t\tlet breakPenalty = 0;\n\t\t\tif (j < n) {\n\t\t\t\tconst prevChild = children[j - 1];\n\n\t\t\t\t// 优先级:标点 > 空格 > CJK 词界 > 普通文本\n\t\t\t\tif (PUNCTUATION_REGEX.test(prevChild.text)) {\n\t\t\t\t\tbreakPenalty = -(\n\t\t\t\t\t\t(containerWidth * PUNCTUATION_BREAK_REWARD_RATIO) **\n\t\t\t\t\t\t2\n\t\t\t\t\t);\n\t\t\t\t} else if (prevChild.isSpace) {\n\t\t\t\t\tbreakPenalty = -((containerWidth * SPACE_BREAK_REWARD_RATIO) ** 2);\n\t\t\t\t} else if (cjkBoundaries.has(charOffsets[j])) {\n\t\t\t\t\tbreakPenalty = PENALTY_CJK;\n\t\t\t\t} else {\n\t\t\t\t\tbreakPenalty = PENALTY_NORMAL;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst totalCost = lineCost + breakPenalty + dp[j];\n\n\t\t\tif (totalCost < dp[i]) {\n\t\t\t\tdp[i] = totalCost;\n\t\t\t\tnextBreak[i] = j;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst breaks: number[] = [];\n\tlet curr = 0;\n\twhile (curr < n) {\n\t\tcurr = nextBreak[curr];\n\t\tif (curr > 0 && curr < n) {\n\t\t\tbreaks.push(curr);\n\t\t}\n\t}\n\n\treturn breaks;\n}\n","import { clampPositive } from \"./clamp.ts\";\nimport { type ChildNodeInfo, calcBalancedBreaks } from \"./lyric-line-break.ts\";\n\nlet sharedCanvasCtx: CanvasRenderingContext2D | null = null;\nexport function getMeasurementContext(): CanvasRenderingContext2D | null {\n\tif (!sharedCanvasCtx) {\n\t\tconst canvas = document.createElement(\"canvas\");\n\t\tsharedCanvasCtx = canvas.getContext(\"2d\");\n\t}\n\treturn sharedCanvasCtx;\n}\n\ninterface LineBalanceAdapter {\n\tresetDOM(): void;\n\tbuildChildInfos(): { childInfos: ChildNodeInfo[]; fullText: string };\n\tapplyBreaks(breaks: number[], childInfos: ChildNodeInfo[]): void;\n\tneedsCalibration: boolean;\n}\n\n/**\n * 用于平衡歌词行在换行后的各行长度\n */\nexport class LineBalancer {\n\tprivate isBalancing = false;\n\tprivate lastBalancedContainerWidth = -1;\n\n\tconstructor(private mainElement: HTMLDivElement) {}\n\n\tpublic balanceLineBreaks(\n\t\tisNonDynamic: boolean,\n\t\thasSplittedWords: boolean,\n\t\twordSegmenter: Intl.Segmenter,\n\t): void {\n\t\tif (this.isBalancing || !this.mainElement) return;\n\n\t\tconst computedStyle = getComputedStyle(this.mainElement);\n\t\tconst paddingLeft = Number.parseFloat(computedStyle.paddingLeft) || 0;\n\t\tconst paddingRight = Number.parseFloat(computedStyle.paddingRight) || 0;\n\t\tconst containerWidth =\n\t\t\tthis.mainElement.clientWidth - paddingLeft - paddingRight;\n\n\t\tif (containerWidth <= 0) return;\n\n\t\tif (isNonDynamic) {\n\t\t\tthis.balanceNonDynamicLineBreaks(\n\t\t\t\tcontainerWidth,\n\t\t\t\tcomputedStyle,\n\t\t\t\twordSegmenter,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!hasSplittedWords) return;\n\t\tthis.balanceDynamicLineBreaks(containerWidth, wordSegmenter);\n\t}\n\n\tpublic reset(): void {\n\t\tthis.lastBalancedContainerWidth = -1;\n\t}\n\n\tprivate executeLineBalance(\n\t\tcontainerWidth: number,\n\t\tadapter: LineBalanceAdapter,\n\t\twordSegmenter: Intl.Segmenter,\n\t): void {\n\t\tconst existingBrs = this.mainElement.querySelectorAll(\"br\");\n\t\tif (\n\t\t\tcontainerWidth === this.lastBalancedContainerWidth &&\n\t\t\texistingBrs.length > 0\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tadapter.resetDOM();\n\n\t\t// 临时设置 white-space: nowrap 以便测量单个歌词行的宽度\n\t\tconst prevWhiteSpace = this.mainElement.style.whiteSpace;\n\t\tthis.mainElement.style.whiteSpace = \"nowrap\";\n\n\t\t// 临时移除父级的 transform 以便让 getBoundingClientRect 返回纯粹的布局尺寸\n\t\t// 基类在 enableScale 时设置的 0.97 缩放倍率会影响到计算的宽度\n\t\tconst parentElement = this.mainElement.parentElement;\n\t\tlet prevTransform = \"\";\n\t\tlet transformChanged = false;\n\n\t\tif (parentElement) {\n\t\t\tprevTransform = parentElement.style.transform;\n\t\t\tif (prevTransform && prevTransform !== \"none\") {\n\t\t\t\tparentElement.style.transform = \"none\";\n\t\t\t\ttransformChanged = true;\n\t\t\t}\n\t\t}\n\n\t\tlet lockAcquired = false;\n\n\t\ttry {\n\t\t\tconst { childInfos, fullText } = adapter.buildChildInfos();\n\n\t\t\tlet layoutWidth = childInfos.reduce((sum, c) => sum + c.width, 0);\n\n\t\t\t// 非动态歌词(用 Canvas 测量)才用 range 来缩放校准;动态歌词的强调 wrapper 有 1em 的 padding 和\n\t\t\t// margin,用 range 测会把首尾溢出的 1em 也加进来,极大地增大了行长度,视觉上就是非常激进地换行\n\t\t\tif (adapter.needsCalibration) {\n\t\t\t\tconst range = document.createRange();\n\t\t\t\trange.selectNodeContents(this.mainElement);\n\t\t\t\tconst visualWidth = range.getBoundingClientRect().width;\n\n\t\t\t\tif (layoutWidth > 0 && visualWidth > 0) {\n\t\t\t\t\tconst scale = visualWidth / layoutWidth;\n\t\t\t\t\tfor (const info of childInfos) {\n\t\t\t\t\t\tinfo.width *= scale;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlayoutWidth = visualWidth;\n\t\t\t}\n\n\t\t\tconst safeContainerWidth = Math.max(1, containerWidth);\n\n\t\t\tif (layoutWidth <= safeContainerWidth) {\n\t\t\t\tthis.lastBalancedContainerWidth = containerWidth;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst breaks = calcBalancedBreaks(\n\t\t\t\tchildInfos,\n\t\t\t\tsafeContainerWidth,\n\t\t\t\tfullText,\n\t\t\t\twordSegmenter,\n\t\t\t);\n\n\t\t\tif (breaks.length === 0) {\n\t\t\t\tthis.lastBalancedContainerWidth = containerWidth;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.isBalancing = true;\n\t\t\tlockAcquired = true;\n\n\t\t\tadapter.applyBreaks(breaks, childInfos);\n\t\t\tthis.lastBalancedContainerWidth = containerWidth;\n\t\t\tthis.isBalancing = false;\n\t\t} finally {\n\t\t\tthis.mainElement.style.whiteSpace = prevWhiteSpace;\n\t\t\tif (transformChanged && parentElement) {\n\t\t\t\tparentElement.style.transform = prevTransform;\n\t\t\t}\n\n\t\t\tif (lockAcquired) {\n\t\t\t\tthis.isBalancing = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate balanceDynamicLineBreaks(\n\t\tcontainerWidth: number,\n\t\twordSegmenter: Intl.Segmenter,\n\t): void {\n\t\tconst infoToNode: Node[] = [];\n\n\t\tconst dynamicAdapter: LineBalanceAdapter = {\n\t\t\tresetDOM: () => {\n\t\t\t\tthis.mainElement.querySelectorAll(\"br\").forEach((br) => {\n\t\t\t\t\tbr.remove();\n\t\t\t\t});\n\t\t\t},\n\t\t\tbuildChildInfos: () => {\n\t\t\t\tinfoToNode.length = 0;\n\t\t\t\tconst childNodes = Array.from(this.mainElement.childNodes);\n\t\t\t\tconst childInfos: ChildNodeInfo[] = [];\n\t\t\t\tconst range = document.createRange();\n\n\t\t\t\tfor (const node of childNodes) {\n\t\t\t\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\t\t\t\tconst text = node.textContent ?? \"\";\n\t\t\t\t\t\tif (text.length === 0) continue;\n\t\t\t\t\t\trange.selectNodeContents(node);\n\t\t\t\t\t\tchildInfos.push({\n\t\t\t\t\t\t\twidth: range.getBoundingClientRect().width,\n\t\t\t\t\t\t\ttext,\n\t\t\t\t\t\t\tisSpace: text.trim().length === 0,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tinfoToNode.push(node);\n\t\t\t\t\t} else if (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\t\t\tconst el = node as HTMLElement;\n\t\t\t\t\t\tconst rect = el.getBoundingClientRect();\n\t\t\t\t\t\tconst elStyle = getComputedStyle(el);\n\t\t\t\t\t\tconst marginLeft = Number.parseFloat(elStyle.marginLeft) || 0;\n\t\t\t\t\t\tconst marginRight = Number.parseFloat(elStyle.marginRight) || 0;\n\t\t\t\t\t\tchildInfos.push({\n\t\t\t\t\t\t\twidth: clampPositive(rect.width + marginLeft + marginRight),\n\t\t\t\t\t\t\ttext: el.textContent ?? \"\",\n\t\t\t\t\t\t\tisSpace: false,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tinfoToNode.push(node);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { childInfos, fullText: childInfos.map((c) => c.text).join(\"\") };\n\t\t\t},\n\t\t\tapplyBreaks: (breaks) => {\n\t\t\t\tfor (let i = breaks.length - 1; i >= 0; i--) {\n\t\t\t\t\tconst breakIndex = breaks[i];\n\t\t\t\t\tif (breakIndex >= 0 && breakIndex < infoToNode.length) {\n\t\t\t\t\t\tthis.mainElement.insertBefore(\n\t\t\t\t\t\t\tdocument.createElement(\"br\"),\n\t\t\t\t\t\t\tinfoToNode[breakIndex],\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tneedsCalibration: false,\n\t\t};\n\n\t\tthis.executeLineBalance(containerWidth, dynamicAdapter, wordSegmenter);\n\t}\n\n\tprivate balanceNonDynamicLineBreaks(\n\t\tcontainerWidth: number,\n\t\tcomputedStyle: CSSStyleDeclaration,\n\t\twordSegmenter: Intl.Segmenter,\n\t): void {\n\t\tconst fullText = this.mainElement.textContent ?? \"\";\n\t\tif (fullText.trim().length === 0) return;\n\n\t\tconst nonDynamicAdapter: LineBalanceAdapter = {\n\t\t\tresetDOM: () => {\n\t\t\t\tthis.mainElement.innerHTML = \"\";\n\t\t\t\tthis.mainElement.textContent = fullText;\n\t\t\t},\n\t\t\tbuildChildInfos: () => {\n\t\t\t\tconst ctx = getMeasurementContext();\n\n\t\t\t\tif (!ctx) {\n\t\t\t\t\tconsole.debug(\n\t\t\t\t\t\t\"Canvas 2D context is not supported, skipping line balancing\",\n\t\t\t\t\t);\n\t\t\t\t\treturn { childInfos: [], fullText };\n\t\t\t\t}\n\n\t\t\t\tctx.font = `${computedStyle.fontWeight} ${computedStyle.fontSize} ${computedStyle.fontFamily}`;\n\n\t\t\t\tif (\"letterSpacing\" in ctx) {\n\t\t\t\t\tctx.letterSpacing =\n\t\t\t\t\t\tcomputedStyle.letterSpacing !== \"normal\"\n\t\t\t\t\t\t\t? computedStyle.letterSpacing\n\t\t\t\t\t\t\t: \"0px\";\n\t\t\t\t}\n\t\t\t\tif (\"wordSpacing\" in ctx) {\n\t\t\t\t\tctx.wordSpacing =\n\t\t\t\t\t\tcomputedStyle.wordSpacing !== \"normal\"\n\t\t\t\t\t\t\t? computedStyle.wordSpacing\n\t\t\t\t\t\t\t: \"0px\";\n\t\t\t\t}\n\n\t\t\t\tconst childInfos: ChildNodeInfo[] = [];\n\t\t\t\tfor (const { segment } of wordSegmenter.segment(fullText)) {\n\t\t\t\t\tchildInfos.push({\n\t\t\t\t\t\twidth: ctx.measureText(segment).width,\n\t\t\t\t\t\ttext: segment,\n\t\t\t\t\t\tisSpace: segment.trim().length === 0,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn { childInfos, fullText };\n\t\t\t},\n\t\t\tapplyBreaks: (breaks, childInfos) => {\n\t\t\t\tthis.mainElement.innerHTML = \"\";\n\t\t\t\tconst breakSet = new Set(breaks);\n\t\t\t\tconst fragment = document.createDocumentFragment();\n\n\t\t\t\tfor (let i = 0; i < childInfos.length; i++) {\n\t\t\t\t\tif (breakSet.has(i)) {\n\t\t\t\t\t\tfragment.appendChild(document.createElement(\"br\"));\n\t\t\t\t\t}\n\t\t\t\t\tfragment.appendChild(document.createTextNode(childInfos[i].text));\n\t\t\t\t}\n\t\t\t\tthis.mainElement.appendChild(fragment);\n\t\t\t},\n\t\t\tneedsCalibration: true,\n\t\t};\n\n\t\tthis.executeLineBalance(containerWidth, nonDynamicAdapter, wordSegmenter);\n\t}\n}\n","import type { LyricWord } from \"../interfaces.ts\";\nimport { isCJK } from \"./is-cjk.ts\";\n\nconst SPLIT_WHITESPACE_RE = /(\\s+)/;\nconst WHITESPACE_RE = /\\s/g;\n\n/**\n * 将输入的单词重新分组,之间没有空格的单词将会组合成一个单词数组\n *\n * 例如输入:`[\"Life\", \" \", \"is\", \" a\", \" su\", \"gar so\", \"sweet\"]`\n *\n * 应该返回:`[\"Life\", \" \", \"is\", \" a\", [\" su\", \"gar\"], \"so\", \"sweet\"]`\n * @param words 输入的单词数组\n * @returns 重新分组后的单词数组\n */\nexport function chunkAndSplitLyricWords(\n\twords: LyricWord[],\n): (LyricWord | LyricWord[])[] {\n\tconst result: (LyricWord | LyricWord[])[] = [];\n\tlet currentGroup: LyricWord[] = [];\n\n\tconst flushGroup = () => {\n\t\tif (currentGroup.length > 0) {\n\t\t\tresult.push(\n\t\t\t\tcurrentGroup.length === 1 ? currentGroup[0] : [...currentGroup],\n\t\t\t);\n\t\t\tcurrentGroup = [];\n\t\t}\n\t};\n\n\tconst processAtom = (atom: LyricWord) => {\n\t\tconst isSpace = atom.word.trim().length === 0;\n\t\tconst hasRuby = (atom.ruby?.length ?? 0) > 0;\n\t\tconst isCJKChar = isCJK(atom.word);\n\n\t\tconst isMergeable = !isSpace && !hasRuby && !isCJKChar;\n\n\t\tif (isMergeable) {\n\t\t\tcurrentGroup.push(atom);\n\t\t} else {\n\t\t\tflushGroup();\n\t\t\tresult.push(atom);\n\t\t}\n\t};\n\n\tfor (const w of words) {\n\t\tconst content = w.word.trim();\n\t\tconst isSpace = content.length === 0;\n\t\tconst romanWord = w.romanWord ?? \"\";\n\t\tconst obscene = w.obscene ?? false;\n\t\tconst hasRuby = (w.ruby?.length ?? 0) > 0;\n\n\t\tif (isSpace || hasRuby) {\n\t\t\tprocessAtom({ ...w });\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst parts = w.word.split(SPLIT_WHITESPACE_RE).filter((p) => p.length > 0);\n\n\t\tconst totalLength = w.word.replace(WHITESPACE_RE, \"\").length || 1;\n\t\tconst timeSpan = w.endTime - w.startTime;\n\t\tconst timePerUnit = timeSpan / totalLength;\n\n\t\tlet currentOffset = 0;\n\n\t\tfor (const part of parts) {\n\t\t\tif (!part.trim()) {\n\t\t\t\tconst startTime = w.startTime + currentOffset * timePerUnit;\n\t\t\t\tprocessAtom({\n\t\t\t\t\tword: part,\n\t\t\t\t\tromanWord: \"\",\n\t\t\t\t\tstartTime: startTime,\n\t\t\t\t\tendTime: startTime,\n\t\t\t\t\tobscene: obscene,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isCJK(part) && part.length > 1 && romanWord.trim().length === 0) {\n\t\t\t\tconst chars = part.split(\"\");\n\t\t\t\tfor (const char of chars) {\n\t\t\t\t\tconst startTime = w.startTime + currentOffset * timePerUnit;\n\t\t\t\t\tprocessAtom({\n\t\t\t\t\t\tword: char,\n\t\t\t\t\t\tromanWord: \"\",\n\t\t\t\t\t\tstartTime: startTime,\n\t\t\t\t\t\tendTime: startTime + timePerUnit,\n\t\t\t\t\t\tobscene: obscene,\n\t\t\t\t\t});\n\t\t\t\t\tcurrentOffset += 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst partRealLen = part.length;\n\t\t\t\tconst startTime = w.startTime + currentOffset * timePerUnit;\n\t\t\t\tconst duration = partRealLen * timePerUnit;\n\n\t\t\t\tprocessAtom({\n\t\t\t\t\tword: part,\n\t\t\t\t\tromanWord: romanWord,\n\t\t\t\t\tstartTime: startTime,\n\t\t\t\t\tendTime: startTime + duration,\n\t\t\t\t\tobscene: obscene,\n\t\t\t\t});\n\t\t\t\tcurrentOffset += partRealLen;\n\t\t\t}\n\t\t}\n\t}\n\n\tflushGroup();\n\n\treturn result;\n}\n","// biome-ignore format: matrix\nexport type Matrix4 = [\n\tnumber, number, number, number,\n\tnumber, number, number, number,\n\tnumber, number, number, number,\n\tnumber, number, number, number,\n];\n\nexport function createMatrix4(): Matrix4 {\n\t// biome-ignore format: matrix\n\treturn [\n 1, 0, 0, 0,\n 0, 1, 0, 0,\n 0, 0, 1, 0,\n 0, 0, 0, 1\n ];\n}\n\nexport function scaleMatrix4(\n\tm: Matrix4,\n\tscale = 1,\n\torigin = { x: 0, y: 0 },\n): Matrix4 {\n\tconst [ox, oy] = [origin.x, origin.y];\n\t// biome-ignore format: matrix\n\treturn [\n m[0] * scale , m[1] * scale , m[2] * scale , m[3],\n m[4] * scale , m[5] * scale , m[6] * scale , m[7],\n m[8] * scale , m[9] * scale , m[10] * scale, m[11],\n m[12] - ox * scale + ox, m[13] - oy * scale + oy, m[14] , m[15]\n ];\n}\n\nexport function translateMatrix4(m: Matrix4, x = 0, y = 0, z = 0): Matrix4 {\n\t// biome-ignore format: matrix\n\treturn [\n m[0] , m[1] , m[2] , m[3] ,\n m[4] , m[5] , m[6] , m[7] ,\n m[8] , m[9] , m[10] , m[11],\n m[12] + x, m[13] + y, m[14] + z, m[15]\n ];\n}\n\nexport function matrix4ToCSS(m: Matrix4, fractionDigits = 4): string {\n\tconst format = (n: number, _: number) => n.toFixed(fractionDigits);\n\treturn `matrix3d(${m.map(format).join(\", \")})`;\n}\n","import bezier from \"bezier-easing\";\nimport type { LyricLine, LyricWord } from \"#interfaces\";\nimport { LyricLineRenderMode } from \"#lyric/base/consts.ts\";\nimport { LyricLineBase } from \"#lyric/base/line.ts\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { clamp, clamp01, clampPositive } from \"#utils/clamp.ts\";\nimport { isCJK } from \"#utils/is-cjk.ts\";\nimport { LineBalancer } from \"#utils/line-balancer.ts\";\nimport { chunkAndSplitLyricWords } from \"#utils/lyric-split-words.ts\";\nimport { createMatrix4, matrix4ToCSS, scaleMatrix4 } from \"#utils/matrix.ts\";\nimport type { DomLyricPlayer } from \".\";\n\ninterface RealWord extends LyricWord {\n\tmainElement: HTMLSpanElement;\n\tsubElements: HTMLSpanElement[];\n\telementAnimations: Animation[];\n\tmaskAnimations: Animation[];\n\twidth: number;\n\theight: number;\n\tpadding: number;\n\tshouldEmphasize: boolean;\n}\n\nconst ANIMATION_FRAME_QUANTITY = 32;\n\nconst norNum = (min: number, max: number) => (x: number) =>\n\tclamp01((x - min) / (max - min));\nconst EMP_EASING_MID = 0.5;\nconst beginNum = norNum(0, EMP_EASING_MID);\nconst endNum = norNum(EMP_EASING_MID, 1);\n\nconst bezIn = bezier(0.2, 0.4, 0.58, 1.0);\nconst bezOut = bezier(0.3, 0.0, 0.58, 1.0);\n\nconst makeEmpEasing = (mid: number) => {\n\treturn (x: number) => (x < mid ? bezIn(beginNum(x)) : 1 - bezOut(endNum(x)));\n};\n\nfunction generateFadeGradient(\n\twidth: number,\n\tpadding = 0,\n\tbright = \"rgba(0,0,0,var(--bright-mask-alpha, 1.0))\",\n\tdark = \"rgba(0,0,0,var(--dark-mask-alpha, 1.0))\",\n): [string, number] {\n\tconst totalAspect = 2 + width + padding;\n\tconst widthInTotal = width / totalAspect;\n\tconst leftPos = (1 - widthInTotal) / 2;\n\treturn [\n\t\t`linear-gradient(to right,${bright} ${leftPos * 100}%,${dark} ${\n\t\t\t(leftPos + widthInTotal) * 100\n\t\t}%)`,\n\t\ttotalAspect,\n\t];\n}\n\nexport class LyricLineEl extends LyricLineBase {\n\tprivate element: HTMLElement = document.createElement(\"div\");\n\tprivate splittedWords: RealWord[] = [];\n\t// 标记是否已经构建了行内的实际 DOM(单词与动画等)\n\tprivate built = false;\n\n\t// 由 LyricPlayer 来设置\n\tlineSize: number[] = [0, 0];\n\n\tprivate renderMode: LyricLineRenderMode = LyricLineRenderMode.SOLID;\n\n\tprivate currentBrightAlpha = 1.0;\n\tprivate currentDarkAlpha = 0.2;\n\n\tprivate targetBrightAlpha = 1.0;\n\tprivate targetDarkAlpha = 0.2;\n\n\t/**\n\t * 用于平衡换行、尽量减少各行长度差异的类\n\t */\n\tprivate balancer?: LineBalancer;\n\n\tconstructor(\n\t\tprivate lyricPlayer: DomLyricPlayer,\n\t\tprivate lyricLine: LyricLine = {\n\t\t\twords: [],\n\t\t\ttranslatedLyric: \"\",\n\t\t\tromanLyric: \"\",\n\t\t\tstartTime: 0,\n\t\t\tendTime: 0,\n\t\t\tisBG: false,\n\t\t\tisDuet: false,\n\t\t},\n\t) {\n\t\tsuper();\n\t\tthis.element.setAttribute(\"class\", styles.lyricLine);\n\t\tif (this.lyricLine.isBG) {\n\t\t\tthis.element.classList.add(styles.lyricBgLine);\n\t\t}\n\t\tif (this.lyricLine.isDuet) {\n\t\t\tthis.element.classList.add(styles.lyricDuetLine);\n\t\t}\n\t\tthis.element.appendChild(document.createElement(\"div\")); // 歌词行\n\t\tthis.element.appendChild(document.createElement(\"div\")); // 翻译行\n\t\tthis.element.appendChild(document.createElement(\"div\")); // 音译行\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\t\tconst trans = this.element.children[1] as HTMLDivElement;\n\t\tconst roman = this.element.children[2] as HTMLDivElement;\n\t\tmain.setAttribute(\"class\", styles.lyricMainLine);\n\t\ttrans.setAttribute(\"class\", styles.lyricSubLine);\n\t\troman.setAttribute(\"class\", styles.lyricSubLine);\n\t\tif (LyricLineBase.wordSegmenter) {\n\t\t\tthis.balancer = new LineBalancer(main);\n\t\t}\n\t\t// 延迟构建具体行内容,进入可视区(含 overscan)时再构建\n\t\tthis.rebuildStyle();\n\t}\n\n\tareWordsOnSameLine(word1: RealWord, word2: RealWord): boolean {\n\t\tif (word1?.mainElement && word2?.mainElement) {\n\t\t\tconst word1el = word1.mainElement;\n\t\t\tconst word2el = word2.mainElement;\n\n\t\t\tconst rect1 = word1el.getBoundingClientRect();\n\t\t\tconst rect2 = word2el.getBoundingClientRect();\n\n\t\t\t// 检查两个单词的顶部距离是否相等(或者差值很小)\n\t\t\tconst topDifference = Math.abs(rect1.top - rect2.top);\n\n\t\t\t// 如果顶部距离相差很小,可以认为它们在同一行上\n\t\t\treturn topDifference < 10;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tprivate isEnabled = false;\n\tasync enable(\n\t\tmaskAnimationTime: number = this.lyricPlayer.getCurrentTime(),\n\t\tshouldPlay: boolean = this.lyricPlayer.getIsPlaying(),\n\t): Promise<void> {\n\t\tthis.isEnabled = true;\n\t\tthis.element.classList.add(styles.active);\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\n\t\tconst relativeTime = clampPositive(\n\t\t\tmaskAnimationTime - this.lyricLine.startTime,\n\t\t);\n\n\t\tfor (const word of this.splittedWords) {\n\t\t\tfor (const a of word.elementAnimations) {\n\t\t\t\ta.currentTime = relativeTime;\n\t\t\t\ta.playbackRate = 1;\n\n\t\t\t\tconst timing = a.effect?.getComputedTiming();\n\t\t\t\tconst duration = Number(timing?.duration ?? 0);\n\t\t\t\tconst delay = Number(timing?.delay ?? 0);\n\t\t\t\tconst endTime = delay + duration;\n\n\t\t\t\tif (shouldPlay && relativeTime < endTime) a.play();\n\t\t\t\telse a.pause();\n\t\t\t}\n\n\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\tconst t = Math.min(this.totalDuration, relativeTime);\n\t\t\t\ta.currentTime = t;\n\t\t\t\ta.playbackRate = 1;\n\n\t\t\t\tconst timing = a.effect?.getComputedTiming();\n\t\t\t\tconst duration = Number(timing?.duration ?? 0);\n\t\t\t\tconst delay = Number(timing?.delay ?? 0);\n\t\t\t\tconst endTime = delay + duration;\n\n\t\t\t\tif (shouldPlay && t < endTime) a.play();\n\t\t\t\telse a.pause();\n\t\t\t}\n\t\t}\n\t\tmain.classList.add(styles.active);\n\t}\n\n\tdisable(): void {\n\t\tthis.isEnabled = false;\n\t\tthis.element.classList.remove(styles.active);\n\t\tthis.renderMode = LyricLineRenderMode.SOLID;\n\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\n\t\tfor (const word of this.splittedWords) {\n\t\t\tfor (const a of word.elementAnimations) {\n\t\t\t\tif (\n\t\t\t\t\ta.id === \"float-word\" ||\n\t\t\t\t\ta.id.includes(\"emphasize-word-float-only\")\n\t\t\t\t) {\n\t\t\t\t\ta.playbackRate = -1;\n\t\t\t\t\ta.play();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\ta.pause();\n\t\t\t}\n\t\t}\n\t\tmain.classList.remove(styles.active);\n\t}\n\n\tprivate lastWord?: RealWord;\n\n\tasync resume(): Promise<void> {\n\t\tif (!this.isEnabled) return;\n\t\tfor (const word of this.splittedWords) {\n\t\t\tfor (const a of word.elementAnimations) {\n\t\t\t\tif (\n\t\t\t\t\t!this.lastWord ||\n\t\t\t\t\tthis.splittedWords.indexOf(this.lastWord) <\n\t\t\t\t\t\tthis.splittedWords.indexOf(word)\n\t\t\t\t) {\n\t\t\t\t\tconst timing = a.effect?.getComputedTiming();\n\t\t\t\t\tconst duration = (timing?.duration as number) || 0;\n\t\t\t\t\tconst delay = (timing?.delay as number) || 0;\n\t\t\t\t\tconst endTime = delay + duration;\n\t\t\t\t\tconst currentTime = (a.currentTime as number) || 0;\n\n\t\t\t\t\tif (a.playState !== \"finished\" && currentTime < endTime) {\n\t\t\t\t\t\ta.play();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\tif (\n\t\t\t\t\t!this.lastWord ||\n\t\t\t\t\tthis.splittedWords.indexOf(this.lastWord) <\n\t\t\t\t\t\tthis.splittedWords.indexOf(word)\n\t\t\t\t) {\n\t\t\t\t\tconst timing = a.effect?.getComputedTiming();\n\t\t\t\t\tconst duration = (timing?.duration as number) || 0;\n\t\t\t\t\tconst delay = (timing?.delay as number) || 0;\n\t\t\t\t\tconst endTime = delay + duration;\n\n\t\t\t\t\tconst currentTime = (a.currentTime as number) || 0;\n\n\t\t\t\t\tif (a.playState !== \"finished\" && currentTime < endTime) {\n\t\t\t\t\t\ta.play();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tif (!this.isEnabled) return;\n\t\tfor (const word of this.splittedWords) {\n\t\t\tfor (const a of word.elementAnimations) {\n\t\t\t\ta.pause();\n\t\t\t}\n\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\ta.pause();\n\t\t\t}\n\t\t}\n\t}\n\tsetMaskAnimationState(maskAnimationTime = 0): void {\n\t\tconst t = maskAnimationTime - this.lyricLine.startTime;\n\t\tfor (const word of this.splittedWords) {\n\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\ta.currentTime = clamp(t, 0, this.totalDuration);\n\t\t\t\ta.playbackRate = 1;\n\t\t\t\tif (t >= 0 && t < this.totalDuration) a.play();\n\t\t\t\telse a.pause();\n\t\t\t}\n\t\t}\n\t}\n\n\tgetLine(): LyricLine {\n\t\treturn this.lyricLine;\n\t}\n\t// private _hide = true;\n\tprivate lastStyle = \"\";\n\tshow(): void {\n\t\tif (!this.built) {\n\t\t\tthis.rebuildElement();\n\t\t\tthis.built = true;\n\t\t\tthis.updateMaskImageSync();\n\t\t}\n\t}\n\n\tprivate rebuildStyle() {\n\t\tlet style = \"\";\n\t\tstyle += `transform: scale(${(this.lineTransforms.scale.getCurrentPosition() / 100).toFixed(4)});`;\n\n\t\tif (!this.lyricPlayer.getEnableSpring()) {\n\t\t\tstyle += `transition-delay:${this.delay}ms;`;\n\t\t}\n\n\t\tstyle += `filter:blur(${Math.min(5, this.blur)}px);`;\n\t\tif (style !== this.lastStyle) {\n\t\t\tthis.lastStyle = style;\n\t\t\tthis.element.setAttribute(\"style\", style);\n\t\t}\n\t}\n\n\toverride rebuildElement(): void {\n\t\tthis.disposeElements();\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\t\tconst trans = this.element.children[1] as HTMLDivElement;\n\t\tconst roman = this.element.children[2] as HTMLDivElement;\n\t\t// 非动态歌词,直接渲染整行与副行\n\t\tif (this.lyricPlayer._getIsNonDynamic()) {\n\t\t\tmain.textContent = this.lyricLine.words\n\t\t\t\t.map((w) => this.lyricPlayer.processObsceneWord(w))\n\t\t\t\t.join(\"\");\n\t\t\tthis.setSubLinesText(trans, roman);\n\t\t\treturn;\n\t\t}\n\n\t\tconst chunkedWords = chunkAndSplitLyricWords(this.lyricLine.words);\n\t\tconst hasRubyLine = this.lyricLine.words.some(\n\t\t\t(word) => (word.ruby?.length ?? 0) > 0,\n\t\t);\n\t\tconst hasRomanLine = this.lyricLine.words.some(\n\t\t\t(word) => (word.romanWord?.trim().length ?? 0) > 0,\n\t\t);\n\t\tmain.innerHTML = \"\";\n\n\t\tfor (const chunk of chunkedWords) {\n\t\t\tthis.buildWord(chunk, main, hasRubyLine, hasRomanLine);\n\t\t}\n\n\t\tthis.setSubLinesText(trans, roman);\n\t}\n\n\t/** 设置翻译与音译行文本 */\n\tprivate setSubLinesText(trans: HTMLDivElement, roman: HTMLDivElement) {\n\t\ttrans.textContent = this.lyricLine.translatedLyric;\n\t\troman.textContent = this.lyricLine.romanLyric;\n\t}\n\n\tprivate getRubyCharCount(word: LyricWord) {\n\t\treturn (word.ruby ?? []).reduce(\n\t\t\t(total, ruby) => total + ruby.word.length,\n\t\t\t0,\n\t\t);\n\t}\n\n\tprivate getRubySegments(word: LyricWord) {\n\t\treturn (word.ruby ?? []).filter(\n\t\t\t(ruby) => (ruby?.word?.trim().length ?? 0) > 0,\n\t\t);\n\t}\n\n\tprivate createWord(\n\t\tword: LyricWord,\n\t\tshouldEmphasize: boolean,\n\t\thasRubyLine: boolean,\n\t\thasRomanLine: boolean,\n\t): RealWord {\n\t\tconst mainWordEl = document.createElement(\"span\");\n\t\tconst subElements: HTMLSpanElement[] = [];\n\t\tconst romanWord = word.romanWord?.trim() ?? \"\";\n\t\tconst wordContainer = hasRubyLine\n\t\t\t? document.createElement(\"div\")\n\t\t\t: mainWordEl;\n\n\t\tif (hasRubyLine) {\n\t\t\tconst rubyWordEl = document.createElement(\"div\");\n\t\t\tconst rubySegments = this.getRubySegments(word);\n\t\t\tfor (const ruby of rubySegments) {\n\t\t\t\tconst rubyPartEl = document.createElement(\"span\");\n\t\t\t\trubyPartEl.textContent = ruby.word;\n\t\t\t\trubyPartEl.dataset.startTime = String(ruby.startTime);\n\t\t\t\trubyPartEl.dataset.endTime = String(ruby.endTime);\n\t\t\t\trubyWordEl.appendChild(rubyPartEl);\n\t\t\t}\n\t\t\trubyWordEl.classList.add(styles.rubyWord);\n\t\t\tmainWordEl.classList.add(styles.wordWithRuby);\n\t\t\twordContainer.classList.add(styles.wordBody);\n\t\t\tmainWordEl.appendChild(rubyWordEl);\n\t\t\tmainWordEl.appendChild(wordContainer);\n\t\t}\n\n\t\tconst displayWord = this.lyricPlayer.processObsceneWord(word);\n\n\t\tif (shouldEmphasize) {\n\t\t\tmainWordEl.classList.add(styles.emphasize);\n\t\t\tconst trimmedWord = displayWord.trim();\n\n\t\t\tif (LyricLineBase.graphemeSegmenter) {\n\t\t\t\tfor (const { segment } of LyricLineBase.graphemeSegmenter.segment(\n\t\t\t\t\ttrimmedWord,\n\t\t\t\t)) {\n\t\t\t\t\tconst charEl = document.createElement(\"span\");\n\t\t\t\t\tcharEl.textContent = segment;\n\t\t\t\t\tsubElements.push(charEl);\n\t\t\t\t\twordContainer.appendChild(charEl);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (const segment of Array.from(trimmedWord)) {\n\t\t\t\t\tconst charEl = document.createElement(\"span\");\n\t\t\t\t\tcharEl.textContent = segment;\n\t\t\t\t\tsubElements.push(charEl);\n\t\t\t\t\twordContainer.appendChild(charEl);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (hasRomanLine) {\n\t\t\t\tconst wordEl = document.createElement(\"div\");\n\t\t\t\twordEl.textContent = displayWord.trim();\n\t\t\t\twordContainer.appendChild(wordEl);\n\t\t\t} else if (romanWord.length === 0) {\n\t\t\t\twordContainer.textContent = displayWord.trim();\n\t\t\t}\n\t\t}\n\n\t\tif (hasRomanLine) {\n\t\t\tconst romanWordEl = document.createElement(\"div\");\n\t\t\tromanWordEl.textContent = romanWord.length > 0 ? romanWord : \"\\u00A0\";\n\t\t\tromanWordEl.classList.add(styles.romanWord);\n\t\t\twordContainer.appendChild(romanWordEl);\n\t\t}\n\n\t\tconst realWord: RealWord = {\n\t\t\t...word,\n\t\t\tmainElement: mainWordEl,\n\t\t\tsubElements: subElements,\n\t\t\telementAnimations: [this.initFloatAnimation(word, mainWordEl)],\n\t\t\tmaskAnimations: [],\n\t\t\twidth: 0,\n\t\t\theight: 0,\n\t\t\tpadding: 0,\n\t\t\tshouldEmphasize: shouldEmphasize,\n\t\t};\n\n\t\treturn realWord;\n\t}\n\n\tprivate buildWord(\n\t\tinput: LyricWord | LyricWord[],\n\t\tmain: HTMLDivElement,\n\t\thasRubyLine: boolean,\n\t\thasRomanLine: boolean,\n\t) {\n\t\tconst chunk = Array.isArray(input) ? input : [input];\n\t\tif (chunk.length === 0) return;\n\n\t\tconst isPureSpace = chunk.every((w) => !w.word.trim());\n\t\tif (isPureSpace) {\n\t\t\tconst textContent = chunk.map((w) => w.word).join(\"\");\n\t\t\tmain.appendChild(document.createTextNode(textContent));\n\t\t\treturn;\n\t\t}\n\n\t\tconst merged = chunk.reduce(\n\t\t\t(a, b) => {\n\t\t\t\ta.endTime = Math.max(a.endTime, b.endTime);\n\t\t\t\ta.startTime = Math.min(a.startTime, b.startTime);\n\t\t\t\ta.word += b.word;\n\t\t\t\treturn a;\n\t\t\t},\n\t\t\t{\n\t\t\t\tword: \"\",\n\t\t\t\tromanWord: \"\",\n\t\t\t\tstartTime: Number.POSITIVE_INFINITY,\n\t\t\t\tendTime: Number.NEGATIVE_INFINITY,\n\t\t\t\twordType: \"normal\",\n\t\t\t\tobscene: false,\n\t\t\t} as LyricWord,\n\t\t);\n\n\t\tlet emp = chunk.some((word) => LyricLineBase.shouldEmphasize(word));\n\t\tif (!isCJK(merged.word)) {\n\t\t\temp = emp || LyricLineBase.shouldEmphasize(merged);\n\t\t}\n\n\t\tconst wrapperWordEl = document.createElement(\"span\");\n\t\twrapperWordEl.classList.add(styles.emphasizeWrapper);\n\n\t\tconst characterElements: HTMLElement[] = [];\n\n\t\tfor (const word of chunk) {\n\t\t\tif (!word.word.trim()) {\n\t\t\t\twrapperWordEl.appendChild(document.createTextNode(word.word));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst realWord = this.createWord(word, emp, hasRubyLine, hasRomanLine);\n\n\t\t\tif (emp) {\n\t\t\t\tcharacterElements.push(...realWord.subElements);\n\t\t\t}\n\n\t\t\tthis.splittedWords.push(realWord);\n\t\t\twrapperWordEl.appendChild(realWord.mainElement);\n\t\t}\n\n\t\tif (emp && this.splittedWords.length > 0) {\n\t\t\tconst lastWordOfChunk = this.splittedWords[this.splittedWords.length - 1];\n\t\t\tconst rubyCharCount = chunk.reduce(\n\t\t\t\t(total, word) => total + this.getRubyCharCount(word),\n\t\t\t\t0,\n\t\t\t);\n\n\t\t\tlastWordOfChunk.elementAnimations.push(\n\t\t\t\t...this.initEmphasizeAnimation(\n\t\t\t\t\tmerged,\n\t\t\t\t\tcharacterElements,\n\t\t\t\t\tmerged.endTime - merged.startTime,\n\t\t\t\t\tmerged.startTime - this.lyricLine.startTime,\n\t\t\t\t\trubyCharCount,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tmain.appendChild(wrapperWordEl);\n\t}\n\n\tprivate initFloatAnimation(word: LyricWord, wordEl: HTMLSpanElement) {\n\t\tconst delay = word.startTime - this.lyricLine.startTime;\n\t\tconst duration = Math.max(1000, word.endTime - word.startTime);\n\t\tlet up = 0.05;\n\t\tif (this.lyricLine.isBG) {\n\t\t\tup *= 2;\n\t\t}\n\t\tconst a = wordEl.animate(\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\ttransform: \"translateY(0px)\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttransform: `translateY(${-up}em)`,\n\t\t\t\t},\n\t\t\t],\n\t\t\t{\n\t\t\t\tduration: Number.isFinite(duration) ? duration : 0,\n\t\t\t\tdelay: Number.isFinite(delay) ? delay : 0,\n\t\t\t\tid: \"float-word\",\n\t\t\t\tcomposite: \"add\",\n\t\t\t\tfill: \"both\",\n\t\t\t\teasing: \"ease-out\",\n\t\t\t},\n\t\t);\n\t\ta.pause();\n\t\treturn a;\n\t}\n\t// 按照原 Apple Music 参考,强调效果只应用缩放、轻微左右位移和辉光效果,原主要的悬浮位移效果不变\n\t// 为了避免产生锯齿抖动感,使用 matrix3d 来实现缩放和位移\n\tprivate initEmphasizeAnimation(\n\t\tword: LyricWord,\n\t\tcharacterElements: HTMLElement[],\n\t\tduration: number,\n\t\tdelay: number,\n\t\trubyCharCount: number,\n\t): Animation[] {\n\t\tconst de = clampPositive(delay);\n\t\tlet du = Math.max(1000, duration);\n\t\tconst anchorCharCount =\n\t\t\trubyCharCount > 0 ? rubyCharCount : Math.max(1, characterElements.length);\n\n\t\tlet result: Animation[] = [];\n\n\t\tlet amount = du / 2000;\n\t\tamount = amount > 1 ? Math.sqrt(amount) : amount ** 3;\n\t\tlet blur = du / 3000;\n\t\tblur = blur > 1 ? Math.sqrt(blur) : blur ** 3;\n\t\tamount *= 0.6;\n\t\tblur *= 0.5;\n\t\tif (\n\t\t\tthis.lyricLine.words.length > 0 &&\n\t\t\tword.word.includes(\n\t\t\t\tthis.lyricLine.words[this.lyricLine.words.length - 1].word,\n\t\t\t)\n\t\t) {\n\t\t\tamount *= 1.6;\n\t\t\tblur *= 1.5;\n\t\t\tdu *= 1.2;\n\t\t}\n\t\tamount = Math.min(1.2, amount);\n\t\tblur = Math.min(0.8, blur);\n\n\t\tconst animateDu = Number.isFinite(du) ? du : 0;\n\t\tconst empEasing = makeEmpEasing(EMP_EASING_MID);\n\n\t\tresult = characterElements.flatMap((el, i, arr) => {\n\t\t\tconst wordDe = de + (du / 2.5 / anchorCharCount) * i;\n\t\t\tconst result: Animation[] = [];\n\n\t\t\tconst frames: Keyframe[] = new Array(ANIMATION_FRAME_QUANTITY)\n\t\t\t\t.fill(0)\n\t\t\t\t.map((_, j) => {\n\t\t\t\t\tconst x = (j + 1) / ANIMATION_FRAME_QUANTITY;\n\t\t\t\t\tconst transX = empEasing(x);\n\t\t\t\t\tconst glowLevel = empEasing(x) * blur;\n\n\t\t\t\t\tconst mat = scaleMatrix4(createMatrix4(), 1 + transX * 0.1 * amount);\n\t\t\t\t\tconst offsetX = -transX * 0.03 * amount * (arr.length / 2 - i);\n\t\t\t\t\tconst offsetY = -transX * 0.025 * amount;\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\toffset: x,\n\t\t\t\t\t\ttransform: `${matrix4ToCSS(\n\t\t\t\t\t\t\tmat,\n\t\t\t\t\t\t\t4,\n\t\t\t\t\t\t)} translate(${offsetX}em, ${offsetY}em)`,\n\t\t\t\t\t\ttextShadow: `0 0 ${Math.min(\n\t\t\t\t\t\t\t0.3,\n\t\t\t\t\t\t\tblur * 0.3,\n\t\t\t\t\t\t)}em rgba(255, 255, 255, ${glowLevel})`,\n\t\t\t\t\t};\n\t\t\t\t});\n\n\t\t\tconst glow = el.animate(frames, {\n\t\t\t\tduration: animateDu,\n\t\t\t\tdelay: Number.isFinite(wordDe) ? wordDe : 0,\n\t\t\t\tid: `emphasize-word-${el.textContent}-${i}`,\n\t\t\t\titerations: 1,\n\t\t\t\tcomposite: \"replace\",\n\t\t\t\tfill: \"both\",\n\t\t\t});\n\t\t\tglow.onfinish = () => {\n\t\t\t\tglow.pause();\n\t\t\t};\n\t\t\tglow.pause();\n\t\t\tresult.push(glow);\n\n\t\t\tconst floatFrame: Keyframe[] = new Array(ANIMATION_FRAME_QUANTITY)\n\t\t\t\t.fill(0)\n\t\t\t\t.map((_, j) => {\n\t\t\t\t\tconst x = (j + 1) / ANIMATION_FRAME_QUANTITY;\n\t\t\t\t\tlet y = Math.sin(x * Math.PI);\n\t\t\t\t\t// y = x < 0.5 ? y : Math.max(y, 1.0);\n\t\t\t\t\tif (this.lyricLine.isBG) {\n\t\t\t\t\t\ty *= 2;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\toffset: x,\n\t\t\t\t\t\ttransform: `translateY(${-y * 0.05}em)`,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\tconst float = el.animate(floatFrame, {\n\t\t\t\tduration: animateDu * 1.4,\n\t\t\t\tdelay: Number.isFinite(wordDe) ? wordDe - 400 : 0,\n\t\t\t\tid: \"emphasize-word-float\",\n\t\t\t\titerations: 1,\n\t\t\t\tcomposite: \"add\",\n\t\t\t\tfill: \"both\",\n\t\t\t});\n\t\t\tfloat.onfinish = () => {\n\t\t\t\tfloat.pause();\n\t\t\t};\n\t\t\tfloat.pause();\n\t\t\tresult.push(float);\n\n\t\t\treturn result;\n\t\t});\n\n\t\treturn result;\n\t}\n\n\tprivate get totalDuration() {\n\t\treturn this.lyricLine.endTime - this.lyricLine.startTime;\n\t}\n\n\toverride onLineSizeChange(_size: [number, number]): void {\n\t\tthis.updateMaskImageSync();\n\t}\n\tupdateMaskImageSync(): void {\n\t\tfor (const word of this.splittedWords) {\n\t\t\tconst el = word.mainElement;\n\t\t\tif (el) {\n\t\t\t\tword.padding = Number.parseFloat(getComputedStyle(el).paddingLeft);\n\t\t\t\tword.width = el.clientWidth - word.padding * 2;\n\t\t\t\tword.height = el.clientHeight - word.padding * 2;\n\t\t\t} else {\n\t\t\t\tword.width = 0;\n\t\t\t\tword.height = 0;\n\t\t\t\tword.padding = 0;\n\t\t\t}\n\t\t}\n\t\tif (this.balancer && LyricLineBase.wordSegmenter) {\n\t\t\tthis.balancer.balanceLineBreaks(\n\t\t\t\tthis.lyricPlayer._getIsNonDynamic(),\n\t\t\t\tthis.splittedWords.length > 0,\n\t\t\t\tLyricLineBase.wordSegmenter,\n\t\t\t);\n\t\t}\n\t\tif (this.lyricPlayer.supportMaskImage) {\n\t\t\tthis.generateWebAnimationBasedMaskImage();\n\t\t} else {\n\t\t\tthis.generateCalcBasedMaskImage();\n\t\t}\n\t\tif (this.isEnabled) {\n\t\t\tconst isPlayerRunning = this.lyricPlayer.getIsPlaying?.() ?? true;\n\t\t\tthis.enable(this.lyricPlayer.getCurrentTime(), isPlayerRunning);\n\t\t}\n\t}\n\n\tprivate generateCalcBasedMaskImage() {\n\t\tfor (const word of this.splittedWords) {\n\t\t\tconst wordEl = word.mainElement;\n\t\t\tif (wordEl) {\n\t\t\t\tword.width = wordEl.clientWidth;\n\t\t\t\tword.height = wordEl.clientHeight;\n\t\t\t\tconst fadeWidth = word.height * this.lyricPlayer.getWordFadeWidth();\n\t\t\t\tconst [maskImage, totalAspect] = generateFadeGradient(\n\t\t\t\t\tfadeWidth / word.width,\n\t\t\t\t);\n\t\t\t\tconst totalAspectStr = `${totalAspect * 100}% 100%`;\n\t\t\t\tif (this.lyricPlayer.supportMaskImage) {\n\t\t\t\t\twordEl.style.maskImage = maskImage;\n\t\t\t\t\twordEl.style.maskRepeat = \"no-repeat\";\n\t\t\t\t\twordEl.style.maskOrigin = \"left\";\n\t\t\t\t\twordEl.style.maskSize = totalAspectStr;\n\t\t\t\t} else {\n\t\t\t\t\twordEl.style.webkitMaskImage = maskImage;\n\t\t\t\t\twordEl.style.webkitMaskRepeat = \"no-repeat\";\n\t\t\t\t\twordEl.style.webkitMaskOrigin = \"left\";\n\t\t\t\t\twordEl.style.webkitMaskSize = totalAspectStr;\n\t\t\t\t}\n\t\t\t\tconst w = word.width + fadeWidth;\n\t\t\t\tconst maskPos = `clamp(${-w}px,calc(${-w}px + (var(--amll-player-time) - ${\n\t\t\t\t\tword.startTime\n\t\t\t\t})*${\n\t\t\t\t\tw / Math.abs(word.endTime - word.startTime)\n\t\t\t\t}px),0px) 0px, left top`;\n\t\t\t\twordEl.style.maskPosition = maskPos;\n\t\t\t\twordEl.style.webkitMaskPosition = maskPos;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate generateWebAnimationBasedMaskImage() {\n\t\t// 因为歌词行有可能比行内单词的结束时间早,有可能导致过渡动画提早停止出现瑕疵\n\t\t// 所以要以单词的结束时间为准\n\t\tconst totalFadeDuration =\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\t...this.splittedWords.map((w) => w.endTime),\n\t\t\t\tthis.lyricLine.endTime,\n\t\t\t) - this.lyricLine.startTime;\n\t\tthis.splittedWords.forEach((word, i) => {\n\t\t\tconst wordEl = word.mainElement;\n\t\t\tif (wordEl) {\n\t\t\t\tconst fadeWidth = word.height * this.lyricPlayer.getWordFadeWidth();\n\t\t\t\tconst [maskImage, totalAspect] = generateFadeGradient(\n\t\t\t\t\tfadeWidth / (word.width + word.padding * 2),\n\t\t\t\t);\n\t\t\t\tconst totalAspectStr = `${totalAspect * 100}% 100%`;\n\t\t\t\tif (this.lyricPlayer.supportMaskImage) {\n\t\t\t\t\twordEl.style.maskImage = maskImage;\n\t\t\t\t\twordEl.style.maskRepeat = \"no-repeat\";\n\t\t\t\t\twordEl.style.maskOrigin = \"left\";\n\t\t\t\t\twordEl.style.maskSize = totalAspectStr;\n\t\t\t\t} else {\n\t\t\t\t\twordEl.style.webkitMaskImage = maskImage;\n\t\t\t\t\twordEl.style.webkitMaskRepeat = \"no-repeat\";\n\t\t\t\t\twordEl.style.webkitMaskOrigin = \"left\";\n\t\t\t\t\twordEl.style.webkitMaskSize = totalAspectStr;\n\t\t\t\t}\n\t\t\t\t// 为了尽可能将渐变动画在相连的每个单词间近似衔接起来\n\t\t\t\t// 要综合每个单词的效果时间和间隙生成动画帧数组\n\t\t\t\tconst widthBeforeSelf =\n\t\t\t\t\tthis.splittedWords.slice(0, i).reduce((a, b) => a + b.width, 0) +\n\t\t\t\t\t(this.splittedWords[0] ? fadeWidth : 0);\n\t\t\t\tconst minOffset = -(word.width + word.padding * 2 + fadeWidth);\n\t\t\t\tconst clampOffset = (x: number) => clamp(x, minOffset, 0);\n\t\t\t\tlet curPos = -widthBeforeSelf - word.width - word.padding - fadeWidth;\n\t\t\t\tlet timeOffset = 0;\n\t\t\t\tconst frames: Keyframe[] = [];\n\t\t\t\tlet lastPos = curPos;\n\t\t\t\tlet lastTime = 0;\n\t\t\t\tconst pushFrame = () => {\n\t\t\t\t\t// 此处如果添加过渡函数,会导致单词时序不准确,所以不添加\n\t\t\t\t\t// const easing = \"cubic-bezier(.33,.12,.83,.9)\";\n\t\t\t\t\tconst moveOffset = curPos - lastPos;\n\t\t\t\t\tconst time = clamp01(timeOffset);\n\t\t\t\t\tconst duration = time - lastTime;\n\t\t\t\t\tconst d = Math.abs(duration / moveOffset);\n\t\t\t\t\t// 因为有可能会和之前的动画有边界\n\t\t\t\t\tif (curPos > minOffset && lastPos < minOffset) {\n\t\t\t\t\t\tconst staticTime = Math.abs(lastPos - minOffset) * d;\n\t\t\t\t\t\tconst value = `${clampOffset(lastPos)}px 0`;\n\t\t\t\t\t\tconst frame: Keyframe = {\n\t\t\t\t\t\t\toffset: lastTime + staticTime,\n\t\t\t\t\t\t\tmaskPosition: value,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tframes.push(frame);\n\t\t\t\t\t}\n\t\t\t\t\tif (curPos > 0 && lastPos < 0) {\n\t\t\t\t\t\tconst staticTime = Math.abs(lastPos) * d;\n\t\t\t\t\t\tconst value = `${clampOffset(curPos)}px 0`;\n\t\t\t\t\t\tconst frame: Keyframe = {\n\t\t\t\t\t\t\toffset: lastTime + staticTime,\n\t\t\t\t\t\t\tmaskPosition: value,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tframes.push(frame);\n\t\t\t\t\t}\n\t\t\t\t\tconst value = `${clampOffset(curPos)}px 0`;\n\t\t\t\t\tconst frame: Keyframe = {\n\t\t\t\t\t\toffset: time,\n\t\t\t\t\t\tmaskPosition: value,\n\t\t\t\t\t};\n\t\t\t\t\tframes.push(frame);\n\t\t\t\t\tlastPos = curPos;\n\t\t\t\t\tlastTime = time;\n\t\t\t\t};\n\t\t\t\tpushFrame();\n\t\t\t\tlet lastTimeStamp = 0;\n\t\t\t\tthis.splittedWords.forEach((otherWord, j) => {\n\t\t\t\t\t// 停顿\n\t\t\t\t\t{\n\t\t\t\t\t\tconst curTimeStamp = otherWord.startTime - this.lyricLine.startTime;\n\t\t\t\t\t\tconst staticDuration = curTimeStamp - lastTimeStamp;\n\t\t\t\t\t\ttimeOffset += staticDuration / totalFadeDuration;\n\t\t\t\t\t\tif (staticDuration > 0) pushFrame();\n\t\t\t\t\t\tlastTimeStamp = curTimeStamp;\n\t\t\t\t\t}\n\t\t\t\t\t// 移动\n\t\t\t\t\t{\n\t\t\t\t\t\tconst fadeDuration = clampPositive(\n\t\t\t\t\t\t\totherWord.endTime - otherWord.startTime,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst rubySegments = this.getRubySegments(otherWord);\n\t\t\t\t\t\tconst rubyCharCount = rubySegments.reduce(\n\t\t\t\t\t\t\t(total, ruby) => total + ruby.word.length,\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (rubyCharCount > 0) {\n\t\t\t\t\t\t\tconst widthPerChar = otherWord.width / rubyCharCount;\n\t\t\t\t\t\t\tlet charIndex = 0;\n\t\t\t\t\t\t\tfor (const ruby of rubySegments) {\n\t\t\t\t\t\t\t\tconst rubyStartTime = Number.isFinite(ruby.startTime)\n\t\t\t\t\t\t\t\t\t? ruby.startTime\n\t\t\t\t\t\t\t\t\t: otherWord.startTime;\n\t\t\t\t\t\t\t\tconst rubyEndTime = Number.isFinite(ruby.endTime)\n\t\t\t\t\t\t\t\t\t? ruby.endTime\n\t\t\t\t\t\t\t\t\t: otherWord.endTime;\n\t\t\t\t\t\t\t\tconst rubyStart = Math.max(rubyStartTime, otherWord.startTime);\n\t\t\t\t\t\t\t\tconst rubyEnd = Math.min(\n\t\t\t\t\t\t\t\t\tMath.max(rubyEndTime, rubyStart),\n\t\t\t\t\t\t\t\t\totherWord.endTime,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tconst rubyStartStamp = rubyStart - this.lyricLine.startTime;\n\t\t\t\t\t\t\t\tconst rubyStaticDuration = rubyStartStamp - lastTimeStamp;\n\t\t\t\t\t\t\t\ttimeOffset += rubyStaticDuration / totalFadeDuration;\n\t\t\t\t\t\t\t\tif (rubyStaticDuration > 0) pushFrame();\n\t\t\t\t\t\t\t\tlastTimeStamp = rubyStartStamp;\n\t\t\t\t\t\t\t\tconst rubyDuration = clampPositive(rubyEnd - rubyStart);\n\t\t\t\t\t\t\t\tconst perCharDuration = rubyDuration / ruby.word.length;\n\t\t\t\t\t\t\t\tfor (\n\t\t\t\t\t\t\t\t\tlet rubyCharIndex = 0;\n\t\t\t\t\t\t\t\t\trubyCharIndex < ruby.word.length;\n\t\t\t\t\t\t\t\t\trubyCharIndex++\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\ttimeOffset += perCharDuration / totalFadeDuration;\n\t\t\t\t\t\t\t\t\tcurPos += widthPerChar;\n\t\t\t\t\t\t\t\t\tif (j === 0 && charIndex === 0) {\n\t\t\t\t\t\t\t\t\t\tcurPos += fadeWidth * 1.5;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\tj === this.splittedWords.length - 1 &&\n\t\t\t\t\t\t\t\t\t\tcharIndex === rubyCharCount - 1\n\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\tcurPos += fadeWidth * 0.5;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (perCharDuration > 0) pushFrame();\n\t\t\t\t\t\t\t\t\tlastTimeStamp += perCharDuration;\n\t\t\t\t\t\t\t\t\tcharIndex++;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst wordEndStamp = Math.max(\n\t\t\t\t\t\t\t\totherWord.endTime - this.lyricLine.startTime,\n\t\t\t\t\t\t\t\tlastTimeStamp,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tconst wordTailDuration = wordEndStamp - lastTimeStamp;\n\t\t\t\t\t\t\ttimeOffset += wordTailDuration / totalFadeDuration;\n\t\t\t\t\t\t\tif (wordTailDuration > 0) pushFrame();\n\t\t\t\t\t\t\tlastTimeStamp = wordEndStamp;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst segmentCount = 1;\n\t\t\t\t\t\t\tconst segmentWidth = otherWord.width / segmentCount;\n\t\t\t\t\t\t\tconst segmentDuration = fadeDuration / segmentCount;\n\t\t\t\t\t\t\tfor (\n\t\t\t\t\t\t\t\tlet segmentIndex = 0;\n\t\t\t\t\t\t\t\tsegmentIndex < segmentCount;\n\t\t\t\t\t\t\t\tsegmentIndex++\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\ttimeOffset += segmentDuration / totalFadeDuration;\n\t\t\t\t\t\t\t\tcurPos += segmentWidth;\n\t\t\t\t\t\t\t\tif (j === 0 && segmentIndex === 0) {\n\t\t\t\t\t\t\t\t\tcurPos += fadeWidth * 1.5;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\tj === this.splittedWords.length - 1 &&\n\t\t\t\t\t\t\t\t\tsegmentIndex === segmentCount - 1\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\tcurPos += fadeWidth * 0.5;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (segmentDuration > 0) pushFrame();\n\t\t\t\t\t\t\t\tlastTimeStamp += segmentDuration;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tfor (const a of word.maskAnimations) {\n\t\t\t\t\ta.cancel();\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\t// TODO: 如果此处动画帧计算出错,需要一个后备方案\n\t\t\t\t\t// 此处如果添加过渡函数,会导致单词时序不准确,所以不添加\n\t\t\t\t\tconst ani = wordEl.animate(frames, {\n\t\t\t\t\t\tduration: totalFadeDuration || 1,\n\t\t\t\t\t\tid: `fade-word-${word.word}-${i}`,\n\t\t\t\t\t\tfill: \"both\",\n\t\t\t\t\t});\n\t\t\t\t\tani.pause();\n\t\t\t\t\tword.maskAnimations = [ani];\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.warn(\"应用渐变动画发生错误\", frames, totalFadeDuration, err);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\tgetElement(): HTMLElement {\n\t\treturn this.element;\n\t}\n\n\tprivate updateMaskAlphaTargets(scale: number) {\n\t\tconst factor = clamp01((scale - 0.97) / 0.03);\n\t\tconst dynamicDarkAlpha = factor * 0.2 + 0.2;\n\t\tconst dynamicBrightAlpha = factor * 0.8 + 0.2;\n\n\t\tif (this.renderMode === LyricLineRenderMode.SOLID) {\n\t\t\tthis.targetBrightAlpha = dynamicDarkAlpha;\n\t\t\tthis.targetDarkAlpha = dynamicDarkAlpha;\n\t\t} else {\n\t\t\tthis.targetBrightAlpha = dynamicBrightAlpha;\n\t\t\tthis.targetDarkAlpha = dynamicDarkAlpha;\n\t\t}\n\t}\n\n\tprivate applyAlphaToDom(delta: number) {\n\t\tconst dt = delta || 0.016;\n\t\tconst ATTACK_SPEED = 50.0;\n\t\tconst RELEASE_SPEED = 7.0;\n\t\tconst getFactor = (speed: number) => 1 - Math.exp(-speed * dt);\n\n\t\t// 根据即将变亮还是变暗选择速度\n\t\t// 如果即将变亮,让速度非常快,以免播放到第一个字的时候透明度还在慢慢增加导致看不清\n\t\tconst isBrightening = this.targetBrightAlpha > this.currentBrightAlpha;\n\t\tconst brightSpeed = isBrightening ? ATTACK_SPEED : RELEASE_SPEED;\n\t\tconst brightFactor = getFactor(brightSpeed);\n\n\t\tif (Math.abs(this.targetBrightAlpha - this.currentBrightAlpha) < 0.001) {\n\t\t\tthis.currentBrightAlpha = this.targetBrightAlpha;\n\t\t} else {\n\t\t\tthis.currentBrightAlpha +=\n\t\t\t\t(this.targetBrightAlpha - this.currentBrightAlpha) * brightFactor;\n\t\t}\n\n\t\tconst isDarkening = this.targetDarkAlpha > this.currentDarkAlpha;\n\t\tconst darkSpeed = isDarkening ? ATTACK_SPEED : RELEASE_SPEED;\n\t\tconst darkFactor = getFactor(darkSpeed);\n\n\t\tif (Math.abs(this.targetDarkAlpha - this.currentDarkAlpha) < 0.001) {\n\t\t\tthis.currentDarkAlpha = this.targetDarkAlpha;\n\t\t} else {\n\t\t\tthis.currentDarkAlpha +=\n\t\t\t\t(this.targetDarkAlpha - this.currentDarkAlpha) * darkFactor;\n\t\t}\n\n\t\tthis.element.style.setProperty(\n\t\t\t\"--bright-mask-alpha\",\n\t\t\tthis.currentBrightAlpha.toFixed(3),\n\t\t);\n\t\tthis.element.style.setProperty(\n\t\t\t\"--dark-mask-alpha\",\n\t\t\tthis.currentDarkAlpha.toFixed(3),\n\t\t);\n\t}\n\n\toverride setTransform(\n\t\tscale: number = this.scale,\n\t\topacity = 1,\n\t\tblur = 0,\n\t\tforce = false,\n\t\tdelay = 0,\n\t\tmode: LyricLineRenderMode = LyricLineRenderMode.SOLID,\n\t): void {\n\t\tsuper.setTransform(scale, opacity, blur, force, delay);\n\n\t\tthis.renderMode = mode;\n\t\tconst enableSpring = this.lyricPlayer.getEnableSpring();\n\n\t\tthis.top = 0;\n\t\tthis.scale = scale;\n\t\tthis.delay = (delay * 1000) | 0;\n\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\t\tmain.style.opacity = `${opacity}`;\n\n\t\tif (force || !enableSpring) {\n\t\t\tthis.blur = Math.min(32, blur);\n\t\t\tthis.lineTransforms.scale.setPosition(scale);\n\n\t\t\tthis.rebuildStyle();\n\n\t\t\tconst currentScale = this.lineTransforms.scale.getCurrentPosition();\n\t\t\tthis.updateMaskAlphaTargets(currentScale / 100);\n\t\t\tthis.currentBrightAlpha = this.targetBrightAlpha;\n\t\t\tthis.currentDarkAlpha = this.targetDarkAlpha;\n\t\t\tthis.element.style.setProperty(\n\t\t\t\t\"--bright-mask-alpha\",\n\t\t\t\tString(this.currentBrightAlpha),\n\t\t\t);\n\t\t\tthis.element.style.setProperty(\n\t\t\t\t\"--dark-mask-alpha\",\n\t\t\t\tString(this.currentDarkAlpha),\n\t\t\t);\n\t\t} else {\n\t\t\tthis.lineTransforms.scale.setTargetPosition(scale);\n\t\t\tif (this.blur !== Math.min(5, blur)) {\n\t\t\t\tthis.blur = Math.min(5, blur);\n\t\t\t\tthis.element.style.filter = `blur(${blur.toFixed(3)}px)`;\n\t\t\t}\n\t\t}\n\t}\n\n\tupdate(delta = 0): void {\n\t\tif (!this.lyricPlayer.getEnableSpring()) return;\n\n\t\tthis.lineTransforms.scale.update(delta);\n\t\tthis.rebuildStyle();\n\n\t\tif (!this.built) return;\n\n\t\tconst currentScale = this.lineTransforms.scale.getCurrentPosition() / 100;\n\t\tthis.updateMaskAlphaTargets(currentScale);\n\t\tthis.applyAlphaToDom(delta);\n\t}\n\n\t/** @internal */\n\t_getDebugTargetPos(): string {\n\t\treturn `[位移: ${this.top}; 缩放: ${this.scale}; 延时: ${this.delay}]`;\n\t}\n\n\tteardownContent(): void {\n\t\tif (this.built) {\n\t\t\tthis.disposeElements();\n\t\t\tthis.built = false;\n\t\t}\n\t}\n\n\tprivate disposeElements() {\n\t\tthis.balancer?.reset();\n\t\tfor (const realWord of this.splittedWords) {\n\t\t\tfor (const a of realWord.elementAnimations) {\n\t\t\t\ta.cancel();\n\t\t\t}\n\t\t\tfor (const a of realWord.maskAnimations) {\n\t\t\t\ta.cancel();\n\t\t\t}\n\t\t\tfor (const sub of realWord.subElements) {\n\t\t\t\tsub.remove();\n\t\t\t\tsub.parentNode?.removeChild(sub);\n\t\t\t}\n\t\t\trealWord.elementAnimations = [];\n\t\t\trealWord.maskAnimations = [];\n\t\t\trealWord.subElements = [];\n\t\t\tif (realWord.mainElement?.parentNode) {\n\t\t\t\trealWord.mainElement.parentNode.removeChild(realWord.mainElement);\n\t\t\t}\n\t\t}\n\t\tthis.splittedWords = [];\n\t\tconst main = this.element.children[0] as HTMLDivElement;\n\t\tconst trans = this.element.children[1] as HTMLDivElement;\n\t\tconst roman = this.element.children[2] as HTMLDivElement;\n\t\tif (main) main.innerHTML = \"\";\n\t\tif (trans) trans.innerHTML = \"\";\n\t\tif (roman) roman.innerHTML = \"\";\n\t}\n\toverride dispose(): void {\n\t\tthis.disposeElements();\n\t\tthis.lyricPlayer.resizeObserver.unobserve(this.element);\n\t\tthis.element.remove();\n\t}\n}\n","/**\n * @fileoverview\n * 一个播放歌词的组件\n * @author SteveXMH\n */\n\nimport type { LyricLine } from \"#interfaces\";\nimport \"#styles/index.css\";\nimport { LyricPlayerBase } from \"#lyric/base/index.ts\";\nimport type { LyricLineBase } from \"#lyric/base/line.ts\";\nimport styles from \"#styles/lyric-player.module.css\";\nimport { LyricLineGroup } from \"./lyric-group.ts\";\nimport { LyricLineEl } from \"./lyric-line.ts\";\n\n/**\n * 歌词行鼠标相关事件,可以获取到歌词行的索引、主歌词行以及背景歌词行(如果有)元素\n */\nexport class LyricLineMouseEvent extends MouseEvent {\n\t/**\n\t * 自定义标志位,用于记录外部是否调用了 `stopPropagation`\n\t */\n\tpublic isPropagationStopped = false;\n\n\tconstructor(\n\t\t/**\n\t\t * 歌词行索引\n\t\t */\n\t\tpublic readonly lineIndex: number,\n\t\t/**\n\t\t * 歌词行元素\n\t\t */\n\t\tpublic readonly line: LyricLineBase,\n\t\t/**\n\t\t * 背景人声歌词行元素 (如果存在)\n\t\t */\n\t\tpublic readonly bgLine: LyricLineBase | undefined,\n\t\tevent: MouseEvent,\n\t) {\n\t\tsuper(`line-${event.type}`, event);\n\t}\n\n\toverride stopPropagation(): void {\n\t\tthis.isPropagationStopped = true;\n\t\tsuper.stopPropagation();\n\t}\n\n\toverride stopImmediatePropagation(): void {\n\t\tthis.isPropagationStopped = true;\n\t\tsuper.stopImmediatePropagation();\n\t}\n}\n\nexport type LyricLineMouseEventListener = (evt: LyricLineMouseEvent) => void;\n\n/**\n * 歌词播放组件,本框架的核心组件\n *\n * 尽可能贴切 Apple Music for iPad 的歌词效果设计,且做了力所能及的优化措施\n */\nexport class DomLyricPlayer extends LyricPlayerBase {\n\tprivate abortController = new AbortController();\n\toverride currentLyricGroups: LyricLineGroup[] = [];\n\n\toverride onResize(): void {\n\t\tconst computedStyles = getComputedStyle(this.element);\n\t\tthis._baseFontSize = Number.parseFloat(computedStyles.fontSize);\n\t\tthis.rebuildStyle();\n\t}\n\n\treadonly supportPlusLighter: boolean = CSS.supports(\n\t\t\"mix-blend-mode\",\n\t\t\"plus-lighter\",\n\t);\n\treadonly supportMaskImage: boolean = CSS.supports(\"mask-image\", \"none\");\n\treadonly innerSize: [number, number] = [0, 0];\n\n\tprivate readonly onMouseEventHandler = (e: MouseEvent) => {\n\t\tconst target = e.target;\n\t\tif (!(target instanceof Element)) return;\n\n\t\tconst groupEl = target.closest(`.${styles.lyricLineWrapper}`);\n\t\tif (!groupEl) return;\n\n\t\tconst group = this.lyricGroupElementMap.get(groupEl);\n\t\tif (!group) return;\n\n\t\tconst mainLine = group.mainLine;\n\t\tconst bgLine = group.bgLine;\n\t\tconst lineIndex = this.lyricLinesIndexes.get(mainLine) ?? -1;\n\n\t\tconst evt = new LyricLineMouseEvent(lineIndex, mainLine, bgLine, e);\n\t\tconst isDispatched = this.dispatchEvent(evt);\n\n\t\tif (!isDispatched || evt.defaultPrevented) {\n\t\t\te.preventDefault();\n\t\t}\n\n\t\tif (evt.isPropagationStopped) {\n\t\t\te.stopPropagation();\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\t};\n\n\t/**\n\t * 是否为非逐词歌词\n\t * @internal\n\t */\n\t_getIsNonDynamic(): boolean {\n\t\treturn this.isNonDynamic;\n\t}\n\tprivate _baseFontSize = Number.parseFloat(\n\t\tgetComputedStyle(this.element).fontSize,\n\t);\n\tpublic get baseFontSize(): number {\n\t\treturn this._baseFontSize;\n\t}\n\tconstructor() {\n\t\tsuper();\n\t\tthis.onResize();\n\t\tthis.element.classList.add(\"amll-lyric-player\", \"dom\");\n\t\tif (this.disableSpring) {\n\t\t\tthis.element.classList.add(styles.disableSpring);\n\t\t}\n\n\t\tthis.element.addEventListener(\"click\", this.onMouseEventHandler, {\n\t\t\tsignal: this.abortController.signal,\n\t\t});\n\t\tthis.element.addEventListener(\"contextmenu\", this.onMouseEventHandler, {\n\t\t\tsignal: this.abortController.signal,\n\t\t});\n\t}\n\n\tprivate rebuildStyle() {\n\t\t// const width = this.innerSize[0];\n\t\t// const height = this.innerSize[1];\n\t\t// this.element.style.setProperty(\"--amll-lp-width\", `${width.toFixed(4)}px`);\n\t\t// this.element.style.setProperty(\n\t\t// \t\"--amll-lp-height\",\n\t\t// \t`${height.toFixed(4)}px`,\n\t\t// );\n\t}\n\n\toverride setWordFadeWidth(value = 0.5): void {\n\t\tsuper.setWordFadeWidth(value);\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.mainLine.updateMaskImageSync();\n\t\t\tgroup.bgLine?.updateMaskImageSync();\n\t\t}\n\t}\n\n\t/**\n\t * 设置当前播放歌词,要注意传入后这个数组内的信息不得修改,否则会发生错误\n\t * @param lines 歌词数组\n\t * @param initialTime 初始时间,默认为 0\n\t */\n\toverride setLyricLines(lines: LyricLine[], initialTime = 0): void {\n\t\tsuper.setLyricLines(lines, initialTime);\n\t\tif (this.hasDuetLine) {\n\t\t\tthis.element.classList.add(styles.hasDuetLine);\n\t\t} else {\n\t\t\tthis.element.classList.remove(styles.hasDuetLine);\n\t\t}\n\t\tif (!this.supportMaskImage) {\n\t\t\tthis.element.style.setProperty(\"--amll-player-time\", `${initialTime}`);\n\t\t}\n\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.dispose();\n\t\t}\n\t\tthis.currentLyricGroups = [];\n\n\t\tlet currentGroup: LyricLineGroup | null = null;\n\n\t\tfor (let i = 0; i < this.processedLines.length; i++) {\n\t\t\tconst line = this.processedLines[i];\n\t\t\tconst lineEl = new LyricLineEl(this, line);\n\n\t\t\tthis.lyricLinesIndexes.set(lineEl, i);\n\n\t\t\tif (!line.isBG || !currentGroup) {\n\t\t\t\tcurrentGroup = new LyricLineGroup(this, lineEl);\n\t\t\t\tthis.currentLyricGroups.push(currentGroup);\n\t\t\t\tthis.lyricGroupElementMap.set(currentGroup.element, currentGroup);\n\t\t\t} else {\n\t\t\t\tcurrentGroup.addBgLine(lineEl);\n\t\t\t}\n\t\t}\n\n\t\tthis.setLinePosXSpringParams({});\n\t\tthis.setLinePosYSpringParams({});\n\t\tthis.setLineScaleSpringParams({});\n\t\tthis.setCurrentTime(initialTime, true);\n\t\tthis.calcLayout(true);\n\t\tthis.update(0);\n\t}\n\n\toverride pause(): void {\n\t\tsuper.pause();\n\t\tthis.element.classList.remove(styles.playing);\n\t\tthis.interludeDots.pause();\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.mainLine.pause();\n\t\t\tgroup.bgLine?.pause();\n\t\t}\n\t}\n\n\toverride resume(): void {\n\t\tsuper.resume();\n\t\tthis.element.classList.add(styles.playing);\n\t\tthis.interludeDots.resume();\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.mainLine.resume();\n\t\t\tgroup.bgLine?.resume();\n\t\t}\n\t}\n\n\toverride update(delta = 0): void {\n\t\tif (!this.timelineState.initialLayoutFinished) return;\n\t\tsuper.update(delta);\n\t\tif (!this.supportMaskImage) {\n\t\t\tthis.element.style.setProperty(\n\t\t\t\t\"--amll-player-time\",\n\t\t\t\t`${this.timelineState.currentTime}`,\n\t\t\t);\n\t\t}\n\t\tif (!this.isPageVisible) return;\n\t\tconst deltaS = delta / 1000;\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.update(deltaS);\n\t\t}\n\t}\n\n\toverride dispose(): void {\n\t\tsuper.dispose();\n\t\tthis.abortController.abort();\n\t\tthis.element.remove();\n\t\tfor (const group of this.currentLyricGroups) {\n\t\t\tgroup.dispose();\n\t\t}\n\t\tthis.bottomLine.dispose();\n\t\tthis.interludeDots.dispose();\n\t}\n}\n"],"mappings":"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"}