@uimaxbai/am-lyrics 1.2.5 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/AmLyrics.d.ts.map +1 -1
- package/dist/src/am-lyrics.js +49 -62
- package/dist/src/am-lyrics.js.map +1 -1
- package/dist/src/react.js +49 -62
- package/dist/src/react.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/fix.cjs +7 -0
- package/package.json +1 -1
- package/patch.diff +210 -0
- package/patch2.diff +26 -0
- package/src/AmLyrics.ts +68 -92
package/src/AmLyrics.ts
CHANGED
|
@@ -2,16 +2,17 @@ import { css, html, LitElement, svg } from 'lit';
|
|
|
2
2
|
import { property, query, state } from 'lit/decorators.js';
|
|
3
3
|
import { GoogleService } from './GoogleService.js';
|
|
4
4
|
|
|
5
|
-
const VERSION = '1.2.
|
|
5
|
+
const VERSION = '1.2.7';
|
|
6
6
|
const INSTRUMENTAL_THRESHOLD_MS = 7000; // Show dots for gaps >= 7s
|
|
7
7
|
const FETCH_TIMEOUT_MS = 8000; // Timeout for all lyrics fetch requests
|
|
8
8
|
const SEEK_THRESHOLD_MS = 500;
|
|
9
9
|
const PRE_SCROLL_LEAD_MS = 500;
|
|
10
|
+
const PRE_SCROLL_LEAD_SHORT_MS = 350;
|
|
10
11
|
const SCROLL_ANIMATION_DURATION_MS = 280;
|
|
11
12
|
const SCROLL_DELAY_INCREMENT_MS = 24;
|
|
12
13
|
const GAP_PULSE_DURATION_MS = 4000;
|
|
13
14
|
const GAP_PULSE_CYCLE_MS = GAP_PULSE_DURATION_MS * 2;
|
|
14
|
-
const GAP_EXIT_LEAD_MS =
|
|
15
|
+
const GAP_EXIT_LEAD_MS = 600;
|
|
15
16
|
const GAP_MIN_SCALE = 0.85;
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -1009,8 +1010,8 @@ export class AmLyrics extends LitElement {
|
|
|
1009
1010
|
0.75em 100%,
|
|
1010
1011
|
0% 100%;
|
|
1011
1012
|
background-position:
|
|
1012
|
-
-0.
|
|
1013
|
-
|
|
1013
|
+
-0.75em 0%,
|
|
1014
|
+
-0.375em 0%;
|
|
1014
1015
|
}
|
|
1015
1016
|
100% {
|
|
1016
1017
|
background-size:
|
|
@@ -1104,7 +1105,7 @@ export class AmLyrics extends LitElement {
|
|
|
1104
1105
|
0.75em 100%,
|
|
1105
1106
|
0% 100%;
|
|
1106
1107
|
background-position:
|
|
1107
|
-
-0.
|
|
1108
|
+
-0.75em 0%,
|
|
1108
1109
|
left;
|
|
1109
1110
|
}
|
|
1110
1111
|
to {
|
|
@@ -1112,7 +1113,7 @@ export class AmLyrics extends LitElement {
|
|
|
1112
1113
|
0.75em 100%,
|
|
1113
1114
|
0% 100%;
|
|
1114
1115
|
background-position:
|
|
1115
|
-
-0.
|
|
1116
|
+
-0.375em 0%,
|
|
1116
1117
|
left;
|
|
1117
1118
|
}
|
|
1118
1119
|
}
|
|
@@ -3274,12 +3275,24 @@ export class AmLyrics extends LitElement {
|
|
|
3274
3275
|
`#lyrics-line-${i}`,
|
|
3275
3276
|
) as HTMLElement;
|
|
3276
3277
|
|
|
3277
|
-
|
|
3278
|
+
const isBackToBack = this.activeLineIndices.length > 0;
|
|
3279
|
+
const leadTime = isBackToBack
|
|
3280
|
+
? PRE_SCROLL_LEAD_SHORT_MS
|
|
3281
|
+
: PRE_SCROLL_LEAD_MS;
|
|
3282
|
+
|
|
3283
|
+
if (timeUntilStart > leadTime) {
|
|
3284
|
+
break; // Lines are ordered by timestamp, no need to check further
|
|
3285
|
+
}
|
|
3286
|
+
|
|
3287
|
+
if (timeUntilStart > 0 && timeUntilStart <= leadTime) {
|
|
3278
3288
|
// Time to pre-scroll and pre-activate!
|
|
3279
3289
|
if (nextLineEl) {
|
|
3280
|
-
// Apply unblur & zoom effect ahead of lyric start
|
|
3281
3290
|
preActiveLineIndex = i;
|
|
3282
|
-
|
|
3291
|
+
|
|
3292
|
+
if (!isBackToBack) {
|
|
3293
|
+
// Apply unblur & zoom effect ahead of lyric start only if no line is currently active
|
|
3294
|
+
nextLineEl.classList.add('pre-active');
|
|
3295
|
+
}
|
|
3283
3296
|
this.clearPreActiveClasses(i);
|
|
3284
3297
|
|
|
3285
3298
|
const slowScrollDuration = Math.max(
|
|
@@ -3289,8 +3302,7 @@ export class AmLyrics extends LitElement {
|
|
|
3289
3302
|
this.focusLine(
|
|
3290
3303
|
nextLineEl,
|
|
3291
3304
|
false,
|
|
3292
|
-
slowScrollDuration,
|
|
3293
|
-
!!currentGap,
|
|
3305
|
+
isBackToBack ? 500 : slowScrollDuration,
|
|
3294
3306
|
);
|
|
3295
3307
|
}
|
|
3296
3308
|
break;
|
|
@@ -4331,71 +4343,29 @@ export class AmLyrics extends LitElement {
|
|
|
4331
4343
|
value: string;
|
|
4332
4344
|
}> = [];
|
|
4333
4345
|
|
|
4334
|
-
// Step 1
|
|
4346
|
+
// Step 1: Grow Pass
|
|
4335
4347
|
if (isGrowable && isFirstSyllable && allWordCharSpans.length > 0) {
|
|
4336
|
-
|
|
4337
|
-
|
|
4348
|
+
const finalDuration = wordDurationMs;
|
|
4349
|
+
const baseDelayPerChar = finalDuration * 0.09;
|
|
4350
|
+
const growDurationMs = finalDuration * 1.5;
|
|
4338
4351
|
|
|
4339
|
-
|
|
4340
|
-
syllable.getAttribute('data-start-time') || '0',
|
|
4341
|
-
);
|
|
4342
|
-
|
|
4343
|
-
allWordCharSpans.forEach((span, charIndexInWord) => {
|
|
4352
|
+
allWordCharSpans.forEach(span => {
|
|
4344
4353
|
const horizontalOffset = parseFloat(
|
|
4345
4354
|
span.dataset.horizontalOffset || '0',
|
|
4346
4355
|
);
|
|
4347
|
-
|
|
4348
4356
|
const maxScale = span.dataset.maxScale || '1.1';
|
|
4349
4357
|
const shadowIntensity = span.dataset.shadowIntensity || '0.6';
|
|
4350
4358
|
const translateYPeak = span.dataset.translateYPeak || '-2';
|
|
4351
4359
|
|
|
4352
|
-
const
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
const parentDuration = parseFloat(
|
|
4357
|
-
parentSyllable.getAttribute('data-duration') || '0',
|
|
4358
|
-
);
|
|
4359
|
-
const parentStartTime = parseFloat(
|
|
4360
|
-
parentSyllable.getAttribute('data-start-time') || '0',
|
|
4361
|
-
);
|
|
4362
|
-
|
|
4363
|
-
const startPct = parseFloat(span.dataset.wipeStart || '0');
|
|
4364
|
-
const durationPct = parseFloat(span.dataset.wipeDuration || '0');
|
|
4365
|
-
|
|
4366
|
-
const relativeStartOffset = Math.max(
|
|
4367
|
-
0,
|
|
4368
|
-
parentStartTime - firstSyllableStartTime,
|
|
4369
|
-
);
|
|
4370
|
-
const wipeDelay = relativeStartOffset + parentDuration * startPct;
|
|
4371
|
-
const wipeDuration = parentDuration * durationPct;
|
|
4372
|
-
|
|
4373
|
-
const useStartAnimation = isFirstInContainer && charIndexInWord === 0;
|
|
4374
|
-
let charWipeAnimation = 'wipe';
|
|
4375
|
-
if (useStartAnimation)
|
|
4376
|
-
charWipeAnimation = isRTL ? 'start-wipe-rtl' : 'start-wipe';
|
|
4377
|
-
else charWipeAnimation = isRTL ? 'wipe-rtl' : 'wipe';
|
|
4378
|
-
|
|
4379
|
-
// Blend word and syllable durations to let the gradient flow smoothly
|
|
4380
|
-
// while still responding to syllable pacing (no strict exactness, just natural flow)
|
|
4381
|
-
const growDelay = wipeDelay;
|
|
4382
|
-
const growDurationMs = Math.max(
|
|
4383
|
-
600,
|
|
4384
|
-
wordDurationMs * 0.8 + parentDuration * 1.5,
|
|
4385
|
-
);
|
|
4386
|
-
|
|
4387
|
-
animationParts.push(
|
|
4388
|
-
`grow-dynamic ${growDurationMs}ms ease-in-out ${growDelay}ms forwards`,
|
|
4389
|
-
);
|
|
4390
|
-
|
|
4391
|
-
if (wipeDuration > 0) {
|
|
4392
|
-
animationParts.push(
|
|
4393
|
-
`${charWipeAnimation} ${wipeDuration}ms linear ${wipeDelay}ms forwards`,
|
|
4394
|
-
);
|
|
4395
|
-
}
|
|
4396
|
-
}
|
|
4360
|
+
const syllableCharIndex = parseFloat(
|
|
4361
|
+
span.dataset.syllableCharIndex || '0',
|
|
4362
|
+
);
|
|
4363
|
+
const growDelay = baseDelayPerChar * syllableCharIndex;
|
|
4397
4364
|
|
|
4398
|
-
charAnimationsMap.set(
|
|
4365
|
+
charAnimationsMap.set(
|
|
4366
|
+
span,
|
|
4367
|
+
`grow-dynamic ${growDurationMs}ms ease-in-out ${growDelay}ms forwards`,
|
|
4368
|
+
);
|
|
4399
4369
|
|
|
4400
4370
|
styleUpdates.push({
|
|
4401
4371
|
element: span,
|
|
@@ -4418,31 +4388,10 @@ export class AmLyrics extends LitElement {
|
|
|
4418
4388
|
value: `${translateYPeak}`,
|
|
4419
4389
|
});
|
|
4420
4390
|
});
|
|
4421
|
-
}
|
|
4422
|
-
// For subsequent syllables of a growable word:
|
|
4423
|
-
// If they already have `grow-dynamic`, it means the first syllable correctly took care of BOTH grow and wipe!
|
|
4424
|
-
// Otherwise, they scrubbed directly into this syllable, so let's at least do the wipe.
|
|
4425
|
-
charSpans.forEach(span => {
|
|
4426
|
-
const existingAnimation =
|
|
4427
|
-
charAnimationsMap.get(span) || span.style.animation || '';
|
|
4428
|
-
if (existingAnimation.includes('grow-dynamic')) return;
|
|
4429
|
-
|
|
4430
|
-
const startPct = parseFloat(span.dataset.wipeStart || '0');
|
|
4431
|
-
const durationPct = parseFloat(span.dataset.wipeDuration || '0');
|
|
4432
|
-
const wipeDelay = syllableDurationMs * startPct;
|
|
4433
|
-
const wipeDuration = syllableDurationMs * durationPct;
|
|
4434
|
-
|
|
4435
|
-
const charWipeAnimation = isRTL ? 'wipe-rtl' : 'wipe';
|
|
4391
|
+
}
|
|
4436
4392
|
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
span,
|
|
4440
|
-
`${charWipeAnimation} ${wipeDuration}ms linear ${wipeDelay}ms forwards`,
|
|
4441
|
-
);
|
|
4442
|
-
}
|
|
4443
|
-
});
|
|
4444
|
-
} else if (charSpans.length > 0) {
|
|
4445
|
-
// Per-character wipe for non-growable words (matching YouLyPlus)
|
|
4393
|
+
// Step 2: Wipe Pass
|
|
4394
|
+
if (charSpans.length > 0) {
|
|
4446
4395
|
charSpans.forEach((span, charIndex) => {
|
|
4447
4396
|
const startPct = parseFloat(span.dataset.wipeStart || '0');
|
|
4448
4397
|
const durationPct = parseFloat(span.dataset.wipeDuration || '0');
|
|
@@ -4458,12 +4407,39 @@ export class AmLyrics extends LitElement {
|
|
|
4458
4407
|
charWipeAnimation = isRTL ? 'wipe-rtl' : 'wipe';
|
|
4459
4408
|
}
|
|
4460
4409
|
|
|
4410
|
+
const existingAnimation =
|
|
4411
|
+
charAnimationsMap.get(span) || span.style.animation || '';
|
|
4412
|
+
|
|
4413
|
+
const animationParts = [];
|
|
4414
|
+
|
|
4415
|
+
if (existingAnimation && existingAnimation.includes('grow-dynamic')) {
|
|
4416
|
+
animationParts.push(existingAnimation.split(',')[0].trim());
|
|
4417
|
+
}
|
|
4418
|
+
if (charIndex > 0) {
|
|
4419
|
+
const arrivalTime = span.dataset.preWipeArrival
|
|
4420
|
+
? parseFloat(span.dataset.preWipeArrival)
|
|
4421
|
+
: wipeDelay;
|
|
4422
|
+
const constantDuration = parseFloat(
|
|
4423
|
+
span.dataset.preWipeDuration || '100',
|
|
4424
|
+
);
|
|
4425
|
+
const animDelay = arrivalTime - constantDuration;
|
|
4426
|
+
|
|
4427
|
+
if (constantDuration > 0) {
|
|
4428
|
+
animationParts.push(
|
|
4429
|
+
`pre-wipe-char ${constantDuration}ms linear ${animDelay}ms forwards`,
|
|
4430
|
+
);
|
|
4431
|
+
}
|
|
4432
|
+
}
|
|
4433
|
+
|
|
4461
4434
|
if (wipeDuration > 0) {
|
|
4462
|
-
|
|
4463
|
-
span,
|
|
4435
|
+
animationParts.push(
|
|
4464
4436
|
`${charWipeAnimation} ${wipeDuration}ms linear ${wipeDelay}ms forwards`,
|
|
4465
4437
|
);
|
|
4466
4438
|
}
|
|
4439
|
+
|
|
4440
|
+
if (animationParts.length > 0) {
|
|
4441
|
+
charAnimationsMap.set(span, animationParts.join(', '));
|
|
4442
|
+
}
|
|
4467
4443
|
});
|
|
4468
4444
|
} else {
|
|
4469
4445
|
// Syllable-level wipe for regular (non-growable) words without chars
|