@braccato/core 1.8.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/dist/README.md +40 -0
- package/dist/engine.d.ts +1 -9
- package/dist/engine.js +38 -84
- package/dist/styles/lyrics.css +0 -2
- package/dist/styles/variables.css +1 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -150,6 +150,46 @@ stylesheet must not be able to configure the module by accident. An empty theme
|
|
|
150
150
|
back to its default. The stylesheet itself goes into the document head under the
|
|
151
151
|
`blyrics-custom-style` id.
|
|
152
152
|
|
|
153
|
+
A comment setting holds one value for every view in the bundle. The target scroll position can
|
|
154
|
+
also be set per view: when `--blyrics-target-scroll-pos-ratio` resolves on `.blyrics-container`, it
|
|
155
|
+
wins over `blyrics-target-scroll-pos-ratio`, so an ordinary selector scopes it to one view. It takes
|
|
156
|
+
a unitless number, clamped to `0` to `1`; anything else falls back to the comment setting. Like the
|
|
157
|
+
other custom properties the module reads, it is read once per theme, so the selector has to match
|
|
158
|
+
before the theme is applied.
|
|
159
|
+
|
|
160
|
+
```css
|
|
161
|
+
/* blyrics-target-scroll-pos-ratio = 0.5; */
|
|
162
|
+
.pip-view .blyrics-container {
|
|
163
|
+
--blyrics-target-scroll-pos-ratio: 0.37;
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Autoscroll grouping and animation
|
|
168
|
+
|
|
169
|
+
`blyrics-early-scroll-consider-s` is a comment setting with an independent default of `0.54`
|
|
170
|
+
seconds. When a lyric reaches its scroll time, the renderer includes nearby upcoming lines in
|
|
171
|
+
its target calculation. Entering the lookahead window alone does not scroll. A line already
|
|
172
|
+
included in a committed scroll does not scroll again when its own time arrives. Seeking,
|
|
173
|
+
resuming autoscroll and relayout can still reposition the view.
|
|
174
|
+
|
|
175
|
+
```css
|
|
176
|
+
/* blyrics-early-scroll-consider-s = 0.54; */
|
|
177
|
+
/* blyrics-line-scroll-duration = 750ms; */
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
New groups scroll immediately. Previous per-line `translate` animations continue and compose
|
|
181
|
+
additively, so their duration does not block the next scroll. The line-scroll duration knobs
|
|
182
|
+
control visual motion. The legacy `--blyrics-lyric-scroll-duration` variable and its
|
|
183
|
+
`--blyrics-lyric-transition-duration` alias have been removed, along with the container transform
|
|
184
|
+
transition. `blyrics-queue-scroll-ms` is ignored, and no timing equation needs balancing.
|
|
185
|
+
Missing or invalid line durations fall back to an internal `750ms` duration; nonpositive resolved
|
|
186
|
+
durations also use that fallback. Themes should set the line-scroll duration knobs directly
|
|
187
|
+
instead of referencing the removed variables.
|
|
188
|
+
|
|
189
|
+
Themes that previously relied on duration-derived lookahead should set their preferred
|
|
190
|
+
`blyrics-early-scroll-consider-s` explicitly. The default remains close to the former default
|
|
191
|
+
of approximately `0.54s`, but a custom animation duration no longer changes grouping.
|
|
192
|
+
|
|
153
193
|
There is no `longWordThreshold`, `lineSyncedDelay` or `disableRichsync` property. Those are theme
|
|
154
194
|
settings (`blyrics-long-word-threshold`, `blyrics-line-synced-animation-delay`,
|
|
155
195
|
`blyrics-disable-richsync`), read from the stylesheet you already hand over. A theme that set one
|
package/dist/README.md
CHANGED
|
@@ -150,6 +150,46 @@ stylesheet must not be able to configure the module by accident. An empty theme
|
|
|
150
150
|
back to its default. The stylesheet itself goes into the document head under the
|
|
151
151
|
`blyrics-custom-style` id.
|
|
152
152
|
|
|
153
|
+
A comment setting holds one value for every view in the bundle. The target scroll position can
|
|
154
|
+
also be set per view: when `--blyrics-target-scroll-pos-ratio` resolves on `.blyrics-container`, it
|
|
155
|
+
wins over `blyrics-target-scroll-pos-ratio`, so an ordinary selector scopes it to one view. It takes
|
|
156
|
+
a unitless number, clamped to `0` to `1`; anything else falls back to the comment setting. Like the
|
|
157
|
+
other custom properties the module reads, it is read once per theme, so the selector has to match
|
|
158
|
+
before the theme is applied.
|
|
159
|
+
|
|
160
|
+
```css
|
|
161
|
+
/* blyrics-target-scroll-pos-ratio = 0.5; */
|
|
162
|
+
.pip-view .blyrics-container {
|
|
163
|
+
--blyrics-target-scroll-pos-ratio: 0.37;
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Autoscroll grouping and animation
|
|
168
|
+
|
|
169
|
+
`blyrics-early-scroll-consider-s` is a comment setting with an independent default of `0.54`
|
|
170
|
+
seconds. When a lyric reaches its scroll time, the renderer includes nearby upcoming lines in
|
|
171
|
+
its target calculation. Entering the lookahead window alone does not scroll. A line already
|
|
172
|
+
included in a committed scroll does not scroll again when its own time arrives. Seeking,
|
|
173
|
+
resuming autoscroll and relayout can still reposition the view.
|
|
174
|
+
|
|
175
|
+
```css
|
|
176
|
+
/* blyrics-early-scroll-consider-s = 0.54; */
|
|
177
|
+
/* blyrics-line-scroll-duration = 750ms; */
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
New groups scroll immediately. Previous per-line `translate` animations continue and compose
|
|
181
|
+
additively, so their duration does not block the next scroll. The line-scroll duration knobs
|
|
182
|
+
control visual motion. The legacy `--blyrics-lyric-scroll-duration` variable and its
|
|
183
|
+
`--blyrics-lyric-transition-duration` alias have been removed, along with the container transform
|
|
184
|
+
transition. `blyrics-queue-scroll-ms` is ignored, and no timing equation needs balancing.
|
|
185
|
+
Missing or invalid line durations fall back to an internal `750ms` duration; nonpositive resolved
|
|
186
|
+
durations also use that fallback. Themes should set the line-scroll duration knobs directly
|
|
187
|
+
instead of referencing the removed variables.
|
|
188
|
+
|
|
189
|
+
Themes that previously relied on duration-derived lookahead should set their preferred
|
|
190
|
+
`blyrics-early-scroll-consider-s` explicitly. The default remains close to the former default
|
|
191
|
+
of approximately `0.54s`, but a custom animation duration no longer changes grouping.
|
|
192
|
+
|
|
153
193
|
There is no `longWordThreshold`, `lineSyncedDelay` or `disableRichsync` property. Those are theme
|
|
154
194
|
settings (`blyrics-long-word-threshold`, `blyrics-line-synced-animation-delay`,
|
|
155
195
|
`blyrics-disable-richsync`), read from the stylesheet you already hand over. A theme that set one
|
package/dist/engine.d.ts
CHANGED
|
@@ -19,10 +19,8 @@ interface AnimEngineViewState {
|
|
|
19
19
|
scrollResumeTime: number;
|
|
20
20
|
scrollPos: number;
|
|
21
21
|
selectedElementIndex: number;
|
|
22
|
-
nextScrollAllowedTime: number;
|
|
23
22
|
wasUserScrolling: boolean;
|
|
24
|
-
|
|
25
|
-
queuedScroll: boolean;
|
|
23
|
+
lastScrollElements: LineData[];
|
|
26
24
|
lastScrollDebugContext: {
|
|
27
25
|
activeElms: LineData[];
|
|
28
26
|
centers: number[];
|
|
@@ -210,12 +208,7 @@ interface AnimationConfig {
|
|
|
210
208
|
waveOscillationDurationMs: number;
|
|
211
209
|
waveOscillationEasing: string;
|
|
212
210
|
};
|
|
213
|
-
scroll: {
|
|
214
|
-
durationMs: number;
|
|
215
|
-
easing: string;
|
|
216
|
-
};
|
|
217
211
|
lineScroll: {
|
|
218
|
-
durationMs: number;
|
|
219
212
|
easing: string;
|
|
220
213
|
differentialEffects: boolean;
|
|
221
214
|
};
|
|
@@ -224,7 +217,6 @@ interface AnimationSettings {
|
|
|
224
217
|
config: AnimationConfig;
|
|
225
218
|
scrollTiming: {
|
|
226
219
|
earlyScrollConsiderS: number;
|
|
227
|
-
queueScrollMs: number;
|
|
228
220
|
};
|
|
229
221
|
}
|
|
230
222
|
export declare function noteVisibilityChange(engine: AnimationEngineInstance): void;
|
package/dist/engine.js
CHANGED
|
@@ -26,18 +26,11 @@ const PAUSING_LYRICS_SCROLL_LOG = "Pausing Lyrics Autoscroll Due to User Scroll"
|
|
|
26
26
|
const USER_SCROLL_RESUME_DELAY_MS = 25000;
|
|
27
27
|
const PASSIVE_USER_SCROLL_RESUME_DELAY_MS = 5000;
|
|
28
28
|
const LYRIC_ENDING_THRESHOLD_S = registerThemeSetting("blyrics-lyric-ending-threshold-s", 0.5);
|
|
29
|
-
const EARLY_SCROLL_CONSIDER = registerThemeSetting("blyrics-early-scroll-consider-s", 0.
|
|
30
|
-
const QUEUE_SCROLL_THRESHOLD = registerThemeSetting("blyrics-queue-scroll-ms", 150);
|
|
29
|
+
const EARLY_SCROLL_CONSIDER = registerThemeSetting("blyrics-early-scroll-consider-s", 0.54);
|
|
31
30
|
const TIME_JUMP_THRESHOLD = 0.5;
|
|
32
31
|
const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
33
|
-
const SCROLL_TIMING_RATIO_BASE_DURATION_MS = 750;
|
|
34
|
-
const SCROLL_TIMING_RATIO_BASE_EARLY_SCROLL_CONSIDER_S = 0.62;
|
|
35
|
-
const SCROLL_TIMING_RATIO_BASE_QUEUE_SCROLL_THRESHOLD_MS = 150;
|
|
36
|
-
const MAX_AUTO_QUEUE_SCROLL_THRESHOLD_MS = 200;
|
|
37
32
|
const SCROLL_PREPARE_LEAD_MS = 120;
|
|
38
|
-
const
|
|
39
|
-
const SCROLL_TIMING_BUFFER_MS = SCROLL_TIMING_RATIO_BASE_TOTAL_MS - SCROLL_TIMING_RATIO_BASE_DURATION_MS;
|
|
40
|
-
const AUTO_QUEUE_SCROLL_RATIO = SCROLL_TIMING_RATIO_BASE_QUEUE_SCROLL_THRESHOLD_MS / SCROLL_TIMING_RATIO_BASE_TOTAL_MS;
|
|
33
|
+
const LINE_SCROLL_FALLBACK_DURATION_MS = 750;
|
|
41
34
|
const SWIPE_LEAD_RATIO = registerThemeSetting("blyrics-swipe-lead-ratio", 0.1);
|
|
42
35
|
const SWIPE_DURATION_RATIO = registerThemeSetting("blyrics-swipe-duration-ratio", 1.6);
|
|
43
36
|
const ENABLE_DEBUG_RENDER = registerThemeSetting("blyrics-debug-renderer", false);
|
|
@@ -125,10 +118,8 @@ export function createAnimationEngineInstance(engineDocument, engineWindow, host
|
|
|
125
118
|
scrollResumeTime: 0,
|
|
126
119
|
scrollPos: 0,
|
|
127
120
|
selectedElementIndex: 0,
|
|
128
|
-
nextScrollAllowedTime: 0,
|
|
129
121
|
wasUserScrolling: false,
|
|
130
|
-
|
|
131
|
-
queuedScroll: false,
|
|
122
|
+
lastScrollElements: [],
|
|
132
123
|
lastScrollDebugContext: {
|
|
133
124
|
activeElms: [],
|
|
134
125
|
centers: [],
|
|
@@ -237,7 +228,6 @@ export function noteUserScroll(engine, isPassive) {
|
|
|
237
228
|
export function noteContainerResize(engine, width, height) {
|
|
238
229
|
if (width === engine.lyricWidth && height === engine.lyricHeight)
|
|
239
230
|
return false;
|
|
240
|
-
engine.nextScrollAllowedTime = 0;
|
|
241
231
|
return true;
|
|
242
232
|
}
|
|
243
233
|
/**
|
|
@@ -282,10 +272,9 @@ export function clearLyrics(engine) {
|
|
|
282
272
|
line.isSelected = false;
|
|
283
273
|
}
|
|
284
274
|
engine.skipScrollsDecayTimes = [];
|
|
285
|
-
engine.
|
|
275
|
+
engine.lastScrollElements = [];
|
|
286
276
|
engine.lastScrollDebugContext.activeElms = [];
|
|
287
277
|
engine.lastScrollDebugContext.centers = [];
|
|
288
|
-
engine.queuedScroll = false;
|
|
289
278
|
engine.passiveScrollAccumulatedTime = 0;
|
|
290
279
|
engine.passiveLastWallTime = 0;
|
|
291
280
|
stopPassiveScrollLoop(engine);
|
|
@@ -1127,6 +1116,11 @@ function getCSSBoolean(engine, lyricsElement, property, fallback) {
|
|
|
1127
1116
|
function getCSSOffset(engine, lyricsElement, property, fallback) {
|
|
1128
1117
|
return Math.max(0, Math.min(1, getCSSNumber(engine, lyricsElement, property, fallback)));
|
|
1129
1118
|
}
|
|
1119
|
+
// The comment setting is shared by every view in a bundle; the custom property lets a theme scope it to one.
|
|
1120
|
+
function getTargetScrollRatio(engine, lyricsElement) {
|
|
1121
|
+
const scoped = Number.parseFloat(getCSSValue(engine, lyricsElement, "--blyrics-target-scroll-pos-ratio", ""));
|
|
1122
|
+
return Number.isFinite(scoped) ? Math.max(0, Math.min(1, scoped)) : SCROLL_POS_OFFSET_RATIO.getNumberValue();
|
|
1123
|
+
}
|
|
1130
1124
|
// Compose the glow filter so the color stays an unresolved var(--blyrics-glow-color).
|
|
1131
1125
|
// Reading a fully composed --blyrics-highlight-glow-filter-* off the container resolves the
|
|
1132
1126
|
// nested color there, which would defeat per-word overrides like
|
|
@@ -1198,7 +1192,6 @@ function isGlowRestingInvisible(glowTo) {
|
|
|
1198
1192
|
}
|
|
1199
1193
|
function readAnimationConfig(engine, lyricsElement) {
|
|
1200
1194
|
const prefersReducedMotion = engine.window.matchMedia(REDUCED_MOTION_QUERY).matches;
|
|
1201
|
-
const scrollDurationMs = getCSSDurationWithFallback(engine, lyricsElement, "--blyrics-lyric-scroll-duration", "650ms");
|
|
1202
1195
|
const scrollEasing = getCSSValue(engine, lyricsElement, "--blyrics-lyric-scroll-timing-function", "cubic-bezier(0.86, 0, 0.2, 1)");
|
|
1203
1196
|
return {
|
|
1204
1197
|
enabled: {
|
|
@@ -1271,53 +1264,21 @@ function readAnimationConfig(engine, lyricsElement) {
|
|
|
1271
1264
|
waveOscillationDurationMs: getCSSDurationWithFallback(engine, lyricsElement, "--blyrics-instrumental-wave-oscillation-duration", "1.25s"),
|
|
1272
1265
|
waveOscillationEasing: getCSSValue(engine, lyricsElement, "--blyrics-instrumental-wave-oscillation-easing", "ease-in-out"),
|
|
1273
1266
|
},
|
|
1274
|
-
scroll: {
|
|
1275
|
-
durationMs: scrollDurationMs,
|
|
1276
|
-
easing: scrollEasing,
|
|
1277
|
-
},
|
|
1278
1267
|
lineScroll: {
|
|
1279
|
-
durationMs: scrollDurationMs,
|
|
1280
1268
|
easing: scrollEasing,
|
|
1281
1269
|
differentialEffects: !prefersReducedMotion,
|
|
1282
1270
|
},
|
|
1283
1271
|
};
|
|
1284
1272
|
}
|
|
1285
|
-
function readScrollTiming(
|
|
1286
|
-
|
|
1287
|
-
const earlyScrollConsiderWasSet = EARLY_SCROLL_CONSIDER.isManuallySet();
|
|
1288
|
-
const queueScrollWasSet = QUEUE_SCROLL_THRESHOLD.isManuallySet();
|
|
1289
|
-
if (earlyScrollConsiderWasSet && queueScrollWasSet) {
|
|
1290
|
-
return {
|
|
1291
|
-
earlyScrollConsiderS: Math.max(0, EARLY_SCROLL_CONSIDER.getNumberValue()),
|
|
1292
|
-
queueScrollMs: Math.max(0, QUEUE_SCROLL_THRESHOLD.getNumberValue()),
|
|
1293
|
-
};
|
|
1294
|
-
}
|
|
1295
|
-
if (earlyScrollConsiderWasSet) {
|
|
1296
|
-
const earlyScrollConsiderS = Math.max(0, EARLY_SCROLL_CONSIDER.getNumberValue());
|
|
1297
|
-
return {
|
|
1298
|
-
earlyScrollConsiderS,
|
|
1299
|
-
queueScrollMs: Math.min(Math.max(0, totalMs - earlyScrollConsiderS * 1000), MAX_AUTO_QUEUE_SCROLL_THRESHOLD_MS),
|
|
1300
|
-
};
|
|
1301
|
-
}
|
|
1302
|
-
if (queueScrollWasSet) {
|
|
1303
|
-
const queueScrollMs = Math.max(0, QUEUE_SCROLL_THRESHOLD.getNumberValue());
|
|
1304
|
-
return {
|
|
1305
|
-
earlyScrollConsiderS: Math.max(0, (totalMs - queueScrollMs) / 1000),
|
|
1306
|
-
queueScrollMs,
|
|
1307
|
-
};
|
|
1308
|
-
}
|
|
1309
|
-
const queueScrollMs = Math.min(totalMs * AUTO_QUEUE_SCROLL_RATIO, MAX_AUTO_QUEUE_SCROLL_THRESHOLD_MS);
|
|
1310
|
-
return {
|
|
1311
|
-
earlyScrollConsiderS: Math.max(0, (totalMs - queueScrollMs) / 1000),
|
|
1312
|
-
queueScrollMs,
|
|
1313
|
-
};
|
|
1273
|
+
function readScrollTiming() {
|
|
1274
|
+
return { earlyScrollConsiderS: Math.max(0, EARLY_SCROLL_CONSIDER.getNumberValue()) };
|
|
1314
1275
|
}
|
|
1315
1276
|
function getAnimationSettings(engine, lyricsElement) {
|
|
1316
1277
|
if (!engine.cachedAnimationSettings) {
|
|
1317
1278
|
const config = readAnimationConfig(engine, lyricsElement);
|
|
1318
1279
|
engine.cachedAnimationSettings = {
|
|
1319
1280
|
config,
|
|
1320
|
-
scrollTiming: readScrollTiming(
|
|
1281
|
+
scrollTiming: readScrollTiming(),
|
|
1321
1282
|
};
|
|
1322
1283
|
}
|
|
1323
1284
|
return engine.cachedAnimationSettings;
|
|
@@ -1557,9 +1518,9 @@ function prepareLineScrollOffsets(engine, lines, activeLineIndex, scrollDeltaPx,
|
|
|
1557
1518
|
const misses = requests.filter(request => !request.timing);
|
|
1558
1519
|
if (misses.length > 0) {
|
|
1559
1520
|
const missItems = misses.map(request => request.item);
|
|
1560
|
-
const durations = batchResolveLineScrollProperty(engine, missItems, "transition-duration", item => lineScrollDurationProperty(item.side,
|
|
1521
|
+
const durations = batchResolveLineScrollProperty(engine, missItems, "transition-duration", item => lineScrollDurationProperty(item.side, LINE_SCROLL_FALLBACK_DURATION_MS, config.lineScroll.differentialEffects), style => {
|
|
1561
1522
|
const durationMs = toMs(style.transitionDuration.split(",")[0].trim());
|
|
1562
|
-
return durationMs > 0 ? durationMs :
|
|
1523
|
+
return durationMs > 0 ? durationMs : LINE_SCROLL_FALLBACK_DURATION_MS;
|
|
1563
1524
|
});
|
|
1564
1525
|
const startEasings = batchResolveLineScrollProperty(engine, missItems, "transition-timing-function", item => lineScrollEasingProperty(item.side, "start", config.lineScroll.easing, config.lineScroll.differentialEffects), style => style.transitionTimingFunction.trim() || config.lineScroll.easing);
|
|
1565
1526
|
const endEasings = batchResolveLineScrollProperty(engine, missItems, "transition-timing-function", item => lineScrollEasingProperty(item.side, "end", config.lineScroll.easing, config.lineScroll.differentialEffects), style => style.transitionTimingFunction.trim() || config.lineScroll.easing);
|
|
@@ -1918,7 +1879,7 @@ export function tickView(engine, currentTime, options) {
|
|
|
1918
1879
|
if (lyricScrollTime >= time - scrollTiming.earlyScrollConsiderS &&
|
|
1919
1880
|
(lyricScrollTime < nextTime || lyricScrollTime < time + lineData.duration)) {
|
|
1920
1881
|
activeElems.push(lineData);
|
|
1921
|
-
if (!engine.
|
|
1882
|
+
if (!engine.lastScrollElements.includes(lineData) && lyricScrollTime >= time) {
|
|
1922
1883
|
newLyricSelected = true;
|
|
1923
1884
|
}
|
|
1924
1885
|
// const timeDelta = lyricScrollTime - time;
|
|
@@ -2032,10 +1993,8 @@ export function tickView(engine, currentTime, options) {
|
|
|
2032
1993
|
if (activeElems.length == 0) {
|
|
2033
1994
|
activeElems.push(lines[0]);
|
|
2034
1995
|
}
|
|
2035
|
-
engine.lastActiveElements = activeElems.filter(elm => lyricScrollTime >= elm.time // remove elements that haven't reached their scroll time yet.
|
|
2036
|
-
);
|
|
2037
1996
|
// Offset so lyrics appear towards the center of the screen.
|
|
2038
|
-
const scrollPosOffset = tabRendererHeight *
|
|
1997
|
+
const scrollPosOffset = tabRendererHeight * getTargetScrollRatio(engine, lyricsElement);
|
|
2039
1998
|
let lastActiveLyric = activeElems[activeElems.length - 1];
|
|
2040
1999
|
let lyricPositions = activeElems
|
|
2041
2000
|
.filter((lineData, index) => {
|
|
@@ -2134,39 +2093,34 @@ export function tickView(engine, currentTime, options) {
|
|
|
2134
2093
|
!engine.wasUserScrolling &&
|
|
2135
2094
|
timeUntilUpcomingScrollMs > 0 &&
|
|
2136
2095
|
timeUntilUpcomingScrollMs <= SCROLL_PREPARE_LEAD_MS &&
|
|
2137
|
-
|
|
2096
|
+
!engine.lastScrollElements.includes(lastActiveLyric) &&
|
|
2138
2097
|
Math.abs(scrollTop - scrollPos) > 2) {
|
|
2139
2098
|
updateVisibleLyricWillChange(engine, lines, scrollTop, scrollPos, tabRendererHeight);
|
|
2140
2099
|
prepareUpcomingLineScroll(engine, getLineScrollItems(engine, lines), lastActiveLyric, scrollPos - scrollTop, scrollTop, scrollPos, tabRendererHeight, animationConfig);
|
|
2141
2100
|
}
|
|
2142
|
-
if (engine.wasUserScrolling || newLyricSelected
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
}
|
|
2156
|
-
}
|
|
2157
|
-
else {
|
|
2158
|
-
dropPendingLineScroll(engine);
|
|
2101
|
+
if (engine.wasUserScrolling || newLyricSelected) {
|
|
2102
|
+
// Remember future lines only when their group is committed, so they cannot scroll
|
|
2103
|
+
// again at their start. Entering the lookahead window alone does not commit a group.
|
|
2104
|
+
engine.lastScrollElements = activeElems;
|
|
2105
|
+
engine.lastScrollDebugContext.lyricScrollTime = lyricScrollTime;
|
|
2106
|
+
engine.lastScrollDebugContext.centers = lyricPositions;
|
|
2107
|
+
engine.lastScrollDebugContext.activeElms = activeElems;
|
|
2108
|
+
if (smoothScroll && Math.abs(scrollTop - scrollPos) > 2) {
|
|
2109
|
+
const scrollDeltaPx = scrollPos - scrollTop;
|
|
2110
|
+
if (animationConfig.enabled.scroll) {
|
|
2111
|
+
updateVisibleLyricWillChange(engine, lines, scrollTop, scrollPos, tabRendererHeight);
|
|
2112
|
+
const lineScrollItems = getLineScrollItems(engine, lines);
|
|
2113
|
+
commitOrPrepareLineScroll(engine, lineScrollItems, lastActiveLyric, scrollDeltaPx, scrollTop, scrollPos, tabRendererHeight, animationConfig);
|
|
2159
2114
|
}
|
|
2160
|
-
scrollTop = scrollPos;
|
|
2161
|
-
engine.scrollPos = scrollTop;
|
|
2162
|
-
tabRenderer.scrollTop = scrollTop;
|
|
2163
|
-
engine.skipScrolls += 1;
|
|
2164
|
-
engine.skipScrollsDecayTimes.push(Date.now() + 2000);
|
|
2165
2115
|
}
|
|
2166
|
-
else
|
|
2167
|
-
|
|
2168
|
-
engine.queuedScroll = true;
|
|
2116
|
+
else {
|
|
2117
|
+
dropPendingLineScroll(engine);
|
|
2169
2118
|
}
|
|
2119
|
+
scrollTop = scrollPos;
|
|
2120
|
+
engine.scrollPos = scrollTop;
|
|
2121
|
+
tabRenderer.scrollTop = scrollTop;
|
|
2122
|
+
engine.skipScrolls += 1;
|
|
2123
|
+
engine.skipScrollsDecayTimes.push(Date.now() + 2000);
|
|
2170
2124
|
}
|
|
2171
2125
|
}
|
|
2172
2126
|
if (engine.wasUserScrolling && engine.scrollResumeTime < Date.now()) {
|
|
@@ -2223,7 +2177,7 @@ function applyScrollPadding(engine) {
|
|
|
2223
2177
|
if (!lyricsElement || !tabRenderer)
|
|
2224
2178
|
return;
|
|
2225
2179
|
const tabRendererHeight = tabRenderer.getBoundingClientRect().height;
|
|
2226
|
-
const scrollPosOffsetRatio =
|
|
2180
|
+
const scrollPosOffsetRatio = getTargetScrollRatio(engine, lyricsElement);
|
|
2227
2181
|
const currentPaddingBottom = Number.parseFloat(engine.window.getComputedStyle(lyricsElement).paddingBottom) || 0;
|
|
2228
2182
|
const lyricsHeightWithoutBottomPadding = Math.max(0, lyricsElement.scrollHeight - currentPaddingBottom);
|
|
2229
2183
|
const lyricLines = lyricsElement.querySelectorAll(`:scope > .${LINE_CLASS}`);
|
package/dist/styles/lyrics.css
CHANGED
|
@@ -21,8 +21,6 @@
|
|
|
21
21
|
padding-bottom: calc(var(--blyrics-padding-bottom));
|
|
22
22
|
padding-top: 2rem;
|
|
23
23
|
position: relative !important;
|
|
24
|
-
transition: transform var(--blyrics-lyric-scroll-duration)
|
|
25
|
-
var(--blyrics-lyric-scroll-timing-function) 0s;
|
|
26
24
|
will-change: transform;
|
|
27
25
|
z-index: 1;
|
|
28
26
|
}
|
|
@@ -143,11 +143,7 @@
|
|
|
143
143
|
--blyrics-background-blur: 100px;
|
|
144
144
|
--blyrics-background-saturate: 2;
|
|
145
145
|
|
|
146
|
-
/*
|
|
147
|
-
--blyrics-lyric-scroll-duration: var(
|
|
148
|
-
--blyrics-lyric-transition-duration,
|
|
149
|
-
650ms
|
|
150
|
-
);
|
|
146
|
+
/* Shared lyric scroll easing */
|
|
151
147
|
--blyrics-lyric-scroll-timing-function: var(
|
|
152
148
|
--blyrics-lyric-transition-timing-function,
|
|
153
149
|
cubic-bezier(0.86, 0, 0.2, 1)
|