@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.
@@ -39,6 +39,7 @@ function clamp1(x) {
39
39
  return Math.max(1, x);
40
40
  }
41
41
  var BaseRenderer = class extends AbstractBaseRenderer {
42
+ canvas;
42
43
  observer;
43
44
  flowSpeed = 1;
44
45
  currerntRenderScale = .75;
@@ -563,10 +564,10 @@ function generateControlPoints(width, height, variationFraction = randomRange(.4
563
564
  }
564
565
  //#endregion
565
566
  //#region \0raw:/home/runner/work/applemusic-like-lyrics/applemusic-like-lyrics/packages/core/src/bg-render/mesh-renderer/mesh.frag.glsl
566
- var mesh_frag_default = "precision highp float;\r\n\r\nvarying vec3 v_color;\r\nvarying vec2 v_uv;\r\nuniform sampler2D u_texture;\r\nuniform float u_time;\r\nuniform float u_volume;\r\nuniform float u_alpha;\r\n\r\n// 预计算常量\r\nconst float INV_255 = 1.0 / 255.0;\r\nconst float HALF_INV_255 = 0.5 / 255.0;\r\nconst float GRADIENT_NOISE_A = 52.9829189;\r\nconst vec2 GRADIENT_NOISE_B = vec2(0.06711056, 0.00583715);\r\n\r\n/* Gradient noise from Jorge Jimenez's presentation: */\r\n/* http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */\r\nfloat gradientNoise(in vec2 uv) {\r\n return fract(GRADIENT_NOISE_A * fract(dot(uv, GRADIENT_NOISE_B)));\r\n}\r\n\r\n// 优化的旋转函数,避免重复计算sin/cos\r\nvec2 rot(vec2 v, float angle) {\r\n float s = sin(angle);\r\n float c = cos(angle);\r\n return vec2(c * v.x - s * v.y, s * v.x + c * v.y);\r\n}\r\n\r\nvoid main() {\r\n // 合并计算以减少指令数\r\n float volumeEffect = u_volume * 2.0;\r\n float timeVolume = u_time + u_volume;\r\n \r\n float dither = INV_255 * gradientNoise(gl_FragCoord.xy) - HALF_INV_255;\r\n vec2 centeredUV = v_uv - vec2(0.2);\r\n vec2 rotatedUV = rot(centeredUV, timeVolume * 2.0);\r\n vec2 finalUV = rotatedUV * max(0.001, 1.0 - volumeEffect) + vec2(0.5);\r\n \r\n vec4 result = texture2D(u_texture, finalUV);\r\n \r\n float alphaVolumeFactor = u_alpha * max(0.5, 1.0 - u_volume * 0.5);\r\n result.rgb *= v_color * alphaVolumeFactor;\r\n result.a *= alphaVolumeFactor;\r\n \r\n result.rgb += vec3(dither);\r\n \r\n float dist = distance(v_uv, vec2(0.5));\r\n float vignette = smoothstep(0.8, 0.3, dist);\r\n float mask = 0.6 + vignette * 0.4;\r\n result.rgb *= mask;\r\n \r\n gl_FragColor = result;\r\n}\r\n";
567
+ var mesh_frag_default = "precision mediump float;\n\nvarying vec3 v_color;\nvarying vec2 v_uv;\nuniform sampler2D u_texture;\nuniform float u_volume;\nuniform float u_alpha;\nuniform float u_sinAngle;\nuniform float u_cosAngle;\n\n// 预计算常量\nconst float INV_255 = 1.0 / 255.0;\nconst float HALF_INV_255 = 0.5 / 255.0;\nconst float GRADIENT_NOISE_A = 52.9829189;\nconst vec2 GRADIENT_NOISE_B = vec2(0.06711056, 0.00583715);\n\nfloat gradientNoise(in vec2 uv) {\n return fract(GRADIENT_NOISE_A * fract(dot(uv, GRADIENT_NOISE_B)));\n}\n\nvoid main() {\n float volumeEffect = u_volume * 2.0;\n\n float dither = INV_255 * gradientNoise(gl_FragCoord.xy) - HALF_INV_255;\n\n vec2 centeredUV = v_uv - vec2(0.2);\n\n vec2 rotatedUV = vec2(\n u_cosAngle * centeredUV.x - u_sinAngle * centeredUV.y,\n u_sinAngle * centeredUV.x + u_cosAngle * centeredUV.y\n );\n\n vec2 finalUV = rotatedUV * max(0.001, 1.0 - volumeEffect) + vec2(0.5);\n \n vec4 result = texture2D(u_texture, finalUV);\n \n float alphaVolumeFactor = u_alpha * max(0.5, 1.0 - u_volume * 0.5);\n result.rgb *= v_color * alphaVolumeFactor;\n result.a *= alphaVolumeFactor;\n \n result.rgb += vec3(dither);\n \n float dist = distance(v_uv, vec2(0.5));\n float vignette = smoothstep(0.8, 0.3, dist);\n float mask = 0.6 + vignette * 0.4;\n result.rgb *= mask;\n \n gl_FragColor = result;\n}\n";
567
568
  //#endregion
568
569
  //#region \0raw:/home/runner/work/applemusic-like-lyrics/applemusic-like-lyrics/packages/core/src/bg-render/mesh-renderer/mesh.vert.glsl
569
- var mesh_vert_default = "precision highp float;\n\nattribute vec2 a_pos;\nattribute vec3 a_color;\nattribute vec2 a_uv;\nvarying vec3 v_color;\nvarying vec2 v_uv;\n\nuniform float u_aspect;\n\nvoid main() {\n v_color = a_color;\n v_uv = a_uv;\n vec2 pos = a_pos;\n if (u_aspect > 1.0) {\n pos.y *= u_aspect;\n } else {\n pos.x /= u_aspect;\n }\n gl_Position = vec4(pos, 0.0, 1.0);\n}\n";
570
+ var mesh_vert_default = "precision mediump float;\n\nattribute vec2 a_pos;\nattribute vec3 a_color;\nattribute vec2 a_uv;\nvarying vec3 v_color;\nvarying vec2 v_uv;\n\nuniform float u_aspect;\n\nvoid main() {\n v_color = a_color;\n v_uv = a_uv;\n vec2 pos = a_pos;\n if (u_aspect > 1.0) {\n pos.y *= u_aspect;\n } else {\n pos.x /= u_aspect;\n }\n gl_Position = vec4(pos, 0.0, 1.0);\n}\n";
570
571
  //#endregion
571
572
  //#region src/bg-render/mesh-renderer/index.ts
572
573
  /**
@@ -597,6 +598,7 @@ function easeInOutSine(x) {
597
598
  return -(Math.cos(Math.PI * x) - 1) / 2;
598
599
  }
599
600
  var GLProgram = class {
601
+ label;
600
602
  gl;
601
603
  program;
602
604
  vertexShader;
@@ -678,6 +680,10 @@ var GLProgram = class {
678
680
  }
679
681
  };
680
682
  var Mesh = class {
683
+ gl;
684
+ attrPos;
685
+ attrColor;
686
+ attrUV;
681
687
  vertexWidth = 0;
682
688
  vertexHeight = 0;
683
689
  vertexBuffer;
@@ -1100,6 +1106,7 @@ var BHPMesh = class extends Mesh {
1100
1106
  }
1101
1107
  };
1102
1108
  var GLTexture = class {
1109
+ gl;
1103
1110
  tex;
1104
1111
  constructor(gl, albumImageData) {
1105
1112
  this.gl = gl;
@@ -1265,11 +1272,14 @@ var MeshGradientRenderer = class extends BaseRenderer {
1265
1272
  gl.clear(gl.COLOR_BUFFER_BIT);
1266
1273
  this.mainProgram.use();
1267
1274
  gl.activeTexture(gl.TEXTURE0);
1268
- this.mainProgram.setUniform1f("u_time", tickTime / 1e4);
1275
+ const uTime = tickTime / 1e4;
1269
1276
  this.mainProgram.setUniform1f("u_aspect", this.manualControl ? 1 : this.canvas.width / this.canvas.height);
1270
1277
  this.mainProgram.setUniform1i("u_texture", 0);
1271
1278
  this.mainProgram.setUniform1f("u_volume", this.volume);
1272
1279
  this.mainProgram.setUniform1f("u_alpha", 1);
1280
+ const angle = (uTime + this.volume) * 2;
1281
+ this.mainProgram.setUniform1f("u_sinAngle", Math.sin(angle));
1282
+ this.mainProgram.setUniform1f("u_cosAngle", Math.cos(angle));
1273
1283
  state.texture.bind();
1274
1284
  state.mesh.bind();
1275
1285
  state.mesh.draw();
@@ -1507,6 +1517,7 @@ var TimedContainer = class extends _pixi_display.Container {
1507
1517
  time = 0;
1508
1518
  };
1509
1519
  var PixiRenderer = class extends BaseRenderer {
1520
+ canvas;
1510
1521
  app;
1511
1522
  curContainer;
1512
1523
  staticMode = false;
@@ -1736,7 +1747,6 @@ var lyric_player_module_default = {
1736
1747
  "bgWrapperHidden": "FmKaba_bgWrapperHidden",
1737
1748
  "bgWrapperTop": "FmKaba_bgWrapperTop",
1738
1749
  "bottomLine": "FmKaba_bottomLine",
1739
- "dirty": "FmKaba_dirty",
1740
1750
  "disableSpring": "FmKaba_disableSpring",
1741
1751
  "duet": "FmKaba_duet",
1742
1752
  "emphasize": "FmKaba_emphasize",
@@ -2174,6 +2184,7 @@ function solveSpring(from, velocity, to, delay = 0, params) {
2174
2184
  //#endregion
2175
2185
  //#region src/lyric-player/base/bottom-line.ts
2176
2186
  var BottomLineEl = class {
2187
+ lyricPlayer;
2177
2188
  element = document.createElement("div");
2178
2189
  left = 0;
2179
2190
  top = 0;
@@ -3276,6 +3287,8 @@ var LyricPlayerBase = class extends EventTarget {
3276
3287
  //#endregion
3277
3288
  //#region src/lyric-player/base/group.ts
3278
3289
  var LyricLineGroupBase = class {
3290
+ mainLine;
3291
+ bgLine;
3279
3292
  posY = new Spring(0);
3280
3293
  bgSlideY = new Spring(-80);
3281
3294
  top = 0;
@@ -3359,6 +3372,7 @@ var LyricLineGroupBase = class {
3359
3372
  //#endregion
3360
3373
  //#region src/lyric-player/dom/lyric-group.ts
3361
3374
  var LyricLineGroup = class extends LyricLineGroupBase {
3375
+ lyricPlayer;
3362
3376
  element;
3363
3377
  bgWrapper;
3364
3378
  lastIsActive;
@@ -3608,6 +3622,7 @@ function getMeasurementContext() {
3608
3622
  * 用于平衡歌词行在换行后的各行长度
3609
3623
  */
3610
3624
  var LineBalancer = class {
3625
+ mainElement;
3611
3626
  isBalancing = false;
3612
3627
  lastBalancedContainerWidth = -1;
3613
3628
  constructor(mainElement) {
@@ -3931,13 +3946,9 @@ function generateFadeGradient(width, padding = 0, bright = "rgba(0,0,0,var(--bri
3931
3946
  const leftPos = (1 - widthInTotal) / 2;
3932
3947
  return [`linear-gradient(to right,${bright} ${leftPos * 100}%,${dark} ${(leftPos + widthInTotal) * 100}%)`, totalAspect];
3933
3948
  }
3934
- var RawLyricLineMouseEvent = class extends MouseEvent {
3935
- constructor(line, event) {
3936
- super(event.type, event);
3937
- this.line = line;
3938
- }
3939
- };
3940
3949
  var LyricLineEl = class extends LyricLineBase {
3950
+ lyricPlayer;
3951
+ lyricLine;
3941
3952
  element = document.createElement("div");
3942
3953
  splittedWords = [];
3943
3954
  built = false;
@@ -3978,33 +3989,6 @@ var LyricLineEl = class extends LyricLineBase {
3978
3989
  if (LyricLineBase.wordSegmenter) this.balancer = new LineBalancer(main);
3979
3990
  this.rebuildStyle();
3980
3991
  }
3981
- listenersMap = /* @__PURE__ */ new Map();
3982
- onMouseEvent = (e) => {
3983
- const wrapped = new RawLyricLineMouseEvent(this, e);
3984
- for (const listener of this.listenersMap.get(e.type) ?? []) listener.call(this, wrapped);
3985
- if (!this.dispatchEvent(wrapped) || wrapped.defaultPrevented) {
3986
- e.preventDefault();
3987
- e.stopPropagation();
3988
- e.stopImmediatePropagation();
3989
- }
3990
- };
3991
- addMouseEventListener(type, callback, options) {
3992
- if (callback) {
3993
- const listeners = this.listenersMap.get(type) ?? /* @__PURE__ */ new Set();
3994
- if (listeners.size === 0) this.element.addEventListener(type, this.onMouseEvent, options);
3995
- listeners.add(callback);
3996
- this.listenersMap.set(type, listeners);
3997
- }
3998
- }
3999
- removeMouseEventListener(type, callback, options) {
4000
- if (callback) {
4001
- const listeners = this.listenersMap.get(type);
4002
- if (listeners) {
4003
- listeners.delete(callback);
4004
- if (listeners.size === 0) this.element.removeEventListener(type, this.onMouseEvent, options);
4005
- }
4006
- }
4007
- }
4008
3992
  areWordsOnSameLine(word1, word2) {
4009
3993
  if (word1?.mainElement && word2?.mainElement) {
4010
3994
  const word1el = word1.mainElement;
@@ -4121,7 +4105,7 @@ var LyricLineEl = class extends LyricLineBase {
4121
4105
  const trans = this.element.children[1];
4122
4106
  const roman = this.element.children[2];
4123
4107
  if (this.lyricPlayer._getIsNonDynamic()) {
4124
- main.innerText = this.lyricLine.words.map((w) => this.lyricPlayer.processObsceneWord(w)).join("");
4108
+ main.textContent = this.lyricLine.words.map((w) => this.lyricPlayer.processObsceneWord(w)).join("");
4125
4109
  this.setSubLinesText(trans, roman);
4126
4110
  return;
4127
4111
  }
@@ -4134,8 +4118,8 @@ var LyricLineEl = class extends LyricLineBase {
4134
4118
  }
4135
4119
  /** 设置翻译与音译行文本 */
4136
4120
  setSubLinesText(trans, roman) {
4137
- trans.innerText = this.lyricLine.translatedLyric;
4138
- roman.innerText = this.lyricLine.romanLyric;
4121
+ trans.textContent = this.lyricLine.translatedLyric;
4122
+ roman.textContent = this.lyricLine.romanLyric;
4139
4123
  }
4140
4124
  getRubyCharCount(word) {
4141
4125
  return (word.ruby ?? []).reduce((total, ruby) => total + ruby.word.length, 0);
@@ -4153,7 +4137,7 @@ var LyricLineEl = class extends LyricLineBase {
4153
4137
  const rubySegments = this.getRubySegments(word);
4154
4138
  for (const ruby of rubySegments) {
4155
4139
  const rubyPartEl = document.createElement("span");
4156
- rubyPartEl.innerText = ruby.word;
4140
+ rubyPartEl.textContent = ruby.word;
4157
4141
  rubyPartEl.dataset.startTime = String(ruby.startTime);
4158
4142
  rubyPartEl.dataset.endTime = String(ruby.endTime);
4159
4143
  rubyWordEl.appendChild(rubyPartEl);
@@ -4170,24 +4154,24 @@ var LyricLineEl = class extends LyricLineBase {
4170
4154
  const trimmedWord = displayWord.trim();
4171
4155
  if (LyricLineBase.graphemeSegmenter) for (const { segment } of LyricLineBase.graphemeSegmenter.segment(trimmedWord)) {
4172
4156
  const charEl = document.createElement("span");
4173
- charEl.innerText = segment;
4157
+ charEl.textContent = segment;
4174
4158
  subElements.push(charEl);
4175
4159
  wordContainer.appendChild(charEl);
4176
4160
  }
4177
4161
  else for (const segment of Array.from(trimmedWord)) {
4178
4162
  const charEl = document.createElement("span");
4179
- charEl.innerText = segment;
4163
+ charEl.textContent = segment;
4180
4164
  subElements.push(charEl);
4181
4165
  wordContainer.appendChild(charEl);
4182
4166
  }
4183
4167
  } else if (hasRomanLine) {
4184
4168
  const wordEl = document.createElement("div");
4185
- wordEl.innerText = displayWord.trim();
4169
+ wordEl.textContent = displayWord.trim();
4186
4170
  wordContainer.appendChild(wordEl);
4187
- } else if (romanWord.length === 0) wordContainer.innerText = displayWord.trim();
4171
+ } else if (romanWord.length === 0) wordContainer.textContent = displayWord.trim();
4188
4172
  if (hasRomanLine) {
4189
4173
  const romanWordEl = document.createElement("div");
4190
- romanWordEl.innerText = romanWord.length > 0 ? romanWord : "\xA0";
4174
+ romanWordEl.textContent = romanWord.length > 0 ? romanWord : "\xA0";
4191
4175
  romanWordEl.classList.add(lyric_player_module_default.romanWord);
4192
4176
  wordContainer.appendChild(romanWordEl);
4193
4177
  }
@@ -4301,7 +4285,7 @@ var LyricLineEl = class extends LyricLineBase {
4301
4285
  const glow = el.animate(frames, {
4302
4286
  duration: animateDu,
4303
4287
  delay: Number.isFinite(wordDe) ? wordDe : 0,
4304
- id: `emphasize-word-${el.innerText}-${i}`,
4288
+ id: `emphasize-word-${el.textContent}-${i}`,
4305
4289
  iterations: 1,
4306
4290
  composite: "replace",
4307
4291
  fill: "both"
@@ -4587,6 +4571,7 @@ var LyricLineEl = class extends LyricLineBase {
4587
4571
  this.updateMaskAlphaTargets(currentScale);
4588
4572
  this.applyAlphaToDom(delta);
4589
4573
  }
4574
+ /** @internal */
4590
4575
  _getDebugTargetPos() {
4591
4576
  return `[位移: ${this.top}; 缩放: ${this.scale}; 延时: ${this.delay}]`;
4592
4577
  }
@@ -4627,13 +4612,29 @@ var LyricLineEl = class extends LyricLineBase {
4627
4612
  //#endregion
4628
4613
  //#region src/lyric-player/dom/index.ts
4629
4614
  /**
4630
- * 歌词行鼠标相关事件,可以获取到歌词行的索引和歌词行元素
4615
+ * 歌词行鼠标相关事件,可以获取到歌词行的索引、主歌词行以及背景歌词行(如果有)元素
4631
4616
  */
4632
4617
  var LyricLineMouseEvent = class extends MouseEvent {
4633
- constructor(lineIndex, line, event) {
4618
+ lineIndex;
4619
+ line;
4620
+ bgLine;
4621
+ /**
4622
+ * 自定义标志位,用于记录外部是否调用了 `stopPropagation`
4623
+ */
4624
+ isPropagationStopped = false;
4625
+ constructor(lineIndex, line, bgLine, event) {
4634
4626
  super(`line-${event.type}`, event);
4635
4627
  this.lineIndex = lineIndex;
4636
4628
  this.line = line;
4629
+ this.bgLine = bgLine;
4630
+ }
4631
+ stopPropagation() {
4632
+ this.isPropagationStopped = true;
4633
+ super.stopPropagation();
4634
+ }
4635
+ stopImmediatePropagation() {
4636
+ this.isPropagationStopped = true;
4637
+ super.stopImmediatePropagation();
4637
4638
  }
4638
4639
  };
4639
4640
  /**
@@ -4642,6 +4643,7 @@ var LyricLineMouseEvent = class extends MouseEvent {
4642
4643
  * 尽可能贴切 Apple Music for iPad 的歌词效果设计,且做了力所能及的优化措施
4643
4644
  */
4644
4645
  var DomLyricPlayer = class extends LyricPlayerBase {
4646
+ abortController = new AbortController();
4645
4647
  currentLyricGroups = [];
4646
4648
  onResize() {
4647
4649
  const computedStyles = getComputedStyle(this.element);
@@ -4651,10 +4653,18 @@ var DomLyricPlayer = class extends LyricPlayerBase {
4651
4653
  supportPlusLighter = CSS.supports("mix-blend-mode", "plus-lighter");
4652
4654
  supportMaskImage = CSS.supports("mask-image", "none");
4653
4655
  innerSize = [0, 0];
4654
- onLineClickedHandler = (e) => {
4655
- const evt = new LyricLineMouseEvent(this.lyricLinesIndexes.get(e.line) ?? -1, e.line, e);
4656
- if (!this.dispatchEvent(evt)) {
4657
- e.preventDefault();
4656
+ onMouseEventHandler = (e) => {
4657
+ const target = e.target;
4658
+ if (!(target instanceof Element)) return;
4659
+ const groupEl = target.closest(`.${lyric_player_module_default.lyricLineWrapper}`);
4660
+ if (!groupEl) return;
4661
+ const group = this.lyricGroupElementMap.get(groupEl);
4662
+ if (!group) return;
4663
+ const mainLine = group.mainLine;
4664
+ const bgLine = group.bgLine;
4665
+ const evt = new LyricLineMouseEvent(this.lyricLinesIndexes.get(mainLine) ?? -1, mainLine, bgLine, e);
4666
+ if (!this.dispatchEvent(evt) || evt.defaultPrevented) e.preventDefault();
4667
+ if (evt.isPropagationStopped) {
4658
4668
  e.stopPropagation();
4659
4669
  e.stopImmediatePropagation();
4660
4670
  }
@@ -4675,6 +4685,8 @@ var DomLyricPlayer = class extends LyricPlayerBase {
4675
4685
  this.onResize();
4676
4686
  this.element.classList.add("amll-lyric-player", "dom");
4677
4687
  if (this.disableSpring) this.element.classList.add(lyric_player_module_default.disableSpring);
4688
+ this.element.addEventListener("click", this.onMouseEventHandler, { signal: this.abortController.signal });
4689
+ this.element.addEventListener("contextmenu", this.onMouseEventHandler, { signal: this.abortController.signal });
4678
4690
  }
4679
4691
  rebuildStyle() {}
4680
4692
  setWordFadeWidth(value = .5) {
@@ -4694,21 +4706,12 @@ var DomLyricPlayer = class extends LyricPlayerBase {
4694
4706
  if (this.hasDuetLine) this.element.classList.add(lyric_player_module_default.hasDuetLine);
4695
4707
  else this.element.classList.remove(lyric_player_module_default.hasDuetLine);
4696
4708
  if (!this.supportMaskImage) this.element.style.setProperty("--amll-player-time", `${initialTime}`);
4697
- for (const group of this.currentLyricGroups) {
4698
- const linesToDispose = [group.mainLine, group.bgLine].filter((line) => !!line);
4699
- for (const line of linesToDispose) {
4700
- line.removeMouseEventListener("click", this.onLineClickedHandler);
4701
- line.removeMouseEventListener("contextmenu", this.onLineClickedHandler);
4702
- }
4703
- group.dispose();
4704
- }
4709
+ for (const group of this.currentLyricGroups) group.dispose();
4705
4710
  this.currentLyricGroups = [];
4706
4711
  let currentGroup = null;
4707
4712
  for (let i = 0; i < this.processedLines.length; i++) {
4708
4713
  const line = this.processedLines[i];
4709
4714
  const lineEl = new LyricLineEl(this, line);
4710
- lineEl.addMouseEventListener("click", this.onLineClickedHandler);
4711
- lineEl.addMouseEventListener("contextmenu", this.onLineClickedHandler);
4712
4715
  this.lyricLinesIndexes.set(lineEl, i);
4713
4716
  if (!line.isBG || !currentGroup) {
4714
4717
  currentGroup = new LyricLineGroup(this, lineEl);
@@ -4751,6 +4754,7 @@ var DomLyricPlayer = class extends LyricPlayerBase {
4751
4754
  }
4752
4755
  dispose() {
4753
4756
  super.dispose();
4757
+ this.abortController.abort();
4754
4758
  this.element.remove();
4755
4759
  for (const group of this.currentLyricGroups) group.dispose();
4756
4760
  this.bottomLine.dispose();