@braccato/core 1.16.3 → 1.16.5
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/engine.d.ts +5 -0
- package/dist/engine.js +49 -14
- package/dist/styles/instrumental.css +0 -5
- package/package.json +1 -1
package/dist/engine.d.ts
CHANGED
|
@@ -272,6 +272,11 @@ export interface LetterMaskSweep {
|
|
|
272
272
|
easing: string;
|
|
273
273
|
}
|
|
274
274
|
export declare function planLetterMaskSweep(swipe: SwipeRamp, letterCount: number, swipeDurationMs: number, rtl: boolean): LetterMaskSweep[];
|
|
275
|
+
export interface LetterWaveTiming {
|
|
276
|
+
delayMs: number;
|
|
277
|
+
durationMs: number;
|
|
278
|
+
}
|
|
279
|
+
export declare function planLetterWave(swipe: SwipeRamp, letterCount: number, wordDurationMs: number, swipeDurationMs: number, swipeLeadMs: number, floatDurationMs: number): LetterWaveTiming[];
|
|
275
280
|
export declare function clearStyleCaches(engine: AnimationEngineInstance): void;
|
|
276
281
|
export declare function parseColorAlpha(value: string): number | null;
|
|
277
282
|
interface PreparedLineScroll {
|
package/dist/engine.js
CHANGED
|
@@ -833,6 +833,43 @@ export function planLetterMaskSweep(swipe, letterCount, swipeDurationMs, rtl) {
|
|
|
833
833
|
return { keyframes, delayMs: 0, durationMs, easing: swipe.easing };
|
|
834
834
|
});
|
|
835
835
|
}
|
|
836
|
+
function swipeRamp(config) {
|
|
837
|
+
return {
|
|
838
|
+
easing: config.highlight.swipeEasing,
|
|
839
|
+
startFrom: config.highlight.swipeStartFrom,
|
|
840
|
+
startTo: config.highlight.swipeStartTo,
|
|
841
|
+
endFrom: config.highlight.swipeEndFrom,
|
|
842
|
+
endTo: config.highlight.swipeEndTo,
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
// How far through its float a letter crests, as a keyframe offset.
|
|
846
|
+
const LETTER_WAVE_CREST_OFFSET = 0.4;
|
|
847
|
+
// When each letter's wave starts, counted from the start of the word, and how long it lasts. A letter
|
|
848
|
+
// crests just as the swipe finishes lighting it. If the swipe lights it faster than the float rises,
|
|
849
|
+
// it starts early enough to make that, which on a short word means before the word itself does. If the
|
|
850
|
+
// swipe lights it slower, it starts as the swipe touches it and its float stretches to crest on time.
|
|
851
|
+
export function planLetterWave(swipe, letterCount, wordDurationMs, swipeDurationMs, swipeLeadMs, floatDurationMs) {
|
|
852
|
+
const riseMs = floatDurationMs * LETTER_WAVE_CREST_OFFSET;
|
|
853
|
+
const windows = computeLetterSwipeWindows({ ...swipe, easing: "linear" }, letterCount, swipeDurationMs);
|
|
854
|
+
const timings = [];
|
|
855
|
+
for (let index = 0; index < letterCount; index++) {
|
|
856
|
+
if (!windows) {
|
|
857
|
+
// No windows for this ramp, so spread the letters evenly over the word.
|
|
858
|
+
timings.push({ delayMs: (wordDurationMs * index) / letterCount, durationMs: floatDurationMs });
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
// The swipe runs swipeLeadMs ahead of the word, so take the lead back off.
|
|
862
|
+
const touchedMs = windows[index].delayMs - swipeLeadMs;
|
|
863
|
+
const litMs = touchedMs + windows[index].durationMs;
|
|
864
|
+
if (litMs - riseMs > touchedMs) {
|
|
865
|
+
timings.push({ delayMs: touchedMs, durationMs: (litMs - touchedMs) / LETTER_WAVE_CREST_OFFSET });
|
|
866
|
+
}
|
|
867
|
+
else {
|
|
868
|
+
timings.push({ delayMs: litMs - riseMs, durationMs: floatDurationMs });
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
return timings;
|
|
872
|
+
}
|
|
836
873
|
function startRichSyncedHighlightAnimations(engine, part, config, swipeTimeMs, wordTimeMs, swipeDurationMs, glowDurationMs, appliedTimingOffsetMs) {
|
|
837
874
|
const animations = [];
|
|
838
875
|
const highlight = part.highlightElement;
|
|
@@ -842,13 +879,7 @@ function startRichSyncedHighlightAnimations(engine, part, config, swipeTimeMs, w
|
|
|
842
879
|
const swipeCurrentTimeMs = correctedAnimationTimeMs(swipeTimeMs, appliedTimingOffsetMs, swipeDurationMs);
|
|
843
880
|
const highlightLetters = part.highlightLetterElements;
|
|
844
881
|
if (highlightLetters && highlightLetters.length > 0) {
|
|
845
|
-
const sweeps = planLetterMaskSweep(
|
|
846
|
-
easing: config.highlight.swipeEasing,
|
|
847
|
-
startFrom: config.highlight.swipeStartFrom,
|
|
848
|
-
startTo: config.highlight.swipeStartTo,
|
|
849
|
-
endFrom: config.highlight.swipeEndFrom,
|
|
850
|
-
endTo: config.highlight.swipeEndTo,
|
|
851
|
-
}, highlightLetters.length, swipeDurationMs, part.highlightElement.classList.contains(RTL_CLASS));
|
|
882
|
+
const sweeps = planLetterMaskSweep(swipeRamp(config), highlightLetters.length, swipeDurationMs, part.highlightElement.classList.contains(RTL_CLASS));
|
|
852
883
|
sweeps.forEach((sweep, index) => {
|
|
853
884
|
const targets = [highlightLetters[index], part.imageLayers?.glowLetters[index]].filter((target) => target !== undefined);
|
|
854
885
|
for (const target of targets) {
|
|
@@ -1000,23 +1031,27 @@ function startWordAnimations(engine, part, config, currentTime, appliedTimingOff
|
|
|
1000
1031
|
{ transform: `translateY(0)${emphasisRest}`, easing: config.letterWave.riseEasing },
|
|
1001
1032
|
{
|
|
1002
1033
|
transform: `${config.letterWave.transform}${emphasisPeak}`,
|
|
1003
|
-
offset:
|
|
1034
|
+
offset: LETTER_WAVE_CREST_OFFSET,
|
|
1004
1035
|
easing: config.letterWave.fallEasing,
|
|
1005
1036
|
},
|
|
1006
1037
|
{ transform: `${config.letterWave.settle}${emphasisRest}` },
|
|
1007
1038
|
];
|
|
1008
1039
|
const letterCount = letters.length;
|
|
1009
|
-
const
|
|
1010
|
-
|
|
1011
|
-
|
|
1040
|
+
const waves = planLetterWave(swipeRamp(config), letterCount, timedDurationMs, swipeDurationMs, swipeLeadMs, config.letterWave.durationMs);
|
|
1041
|
+
// A letter that starts before the word would have a negative delay, which the drift check reads
|
|
1042
|
+
// as the wave running behind once it finishes. Run the wave's clock ahead by the head start
|
|
1043
|
+
// instead, the way the swipe carries its lead, so every delay stays at zero or above.
|
|
1044
|
+
const waveLeadMs = Math.max(0, -Math.min(...waves.map(wave => wave.delayMs)));
|
|
1045
|
+
const cascadeDurationMs = waveLeadMs + Math.max(...waves.map(wave => wave.delayMs + wave.durationMs));
|
|
1046
|
+
const floatStartMs = correctedAnimationTimeMs(wordTimeMs + waveLeadMs, appliedTimingOffsetMs, cascadeDurationMs);
|
|
1012
1047
|
const floatKeyframeSignature = JSON.stringify(floatKeyframes);
|
|
1013
1048
|
for (const set of [part.letterElements, part.highlightLetterElements, part.imageLayers?.glowLetters]) {
|
|
1014
1049
|
set?.forEach((letterElement, index) => {
|
|
1015
1050
|
const animation = trackLyricAnimationTiming(engine, acquireWaveAnimation(engine, letterElement, floatKeyframes, floatKeyframeSignature, {
|
|
1016
|
-
duration:
|
|
1017
|
-
delay: index
|
|
1051
|
+
duration: waves[index].durationMs,
|
|
1052
|
+
delay: waves[index].delayMs + waveLeadMs,
|
|
1018
1053
|
fill: "forwards",
|
|
1019
|
-
}), { appliedTimingOffsetMs, offsetMs:
|
|
1054
|
+
}), { appliedTimingOffsetMs, offsetMs: waveLeadMs });
|
|
1020
1055
|
animation.currentTime = floatStartMs;
|
|
1021
1056
|
wobbleAnimations.push(animation);
|
|
1022
1057
|
});
|
|
@@ -57,11 +57,6 @@
|
|
|
57
57
|
transform: translateY(-4%);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
.blyrics--paused .blyrics--wave-clip {
|
|
61
|
-
transition-duration: 100000000s !important;
|
|
62
|
-
transform: translateY(100%) !important;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
60
|
.blyrics--wave-path {
|
|
66
61
|
/* Set the transform origin to the bottom of the wave shape (y=4). */
|
|
67
62
|
transform-box: fill-box;
|