@braccato/core 1.16.12 → 1.16.14
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.js +33 -10
- package/package.json +1 -1
package/dist/engine.js
CHANGED
|
@@ -122,7 +122,7 @@ export function createAnimationEngineInstance(engineDocument, engineWindow, host
|
|
|
122
122
|
skipScrolls: 0,
|
|
123
123
|
skipScrollsDecayTimes: [],
|
|
124
124
|
scrollResumeTime: 0,
|
|
125
|
-
scrollPos:
|
|
125
|
+
scrollPos: -1,
|
|
126
126
|
selectedElementIndex: 0,
|
|
127
127
|
wasUserScrolling: false,
|
|
128
128
|
lastScrollElements: [],
|
|
@@ -1679,7 +1679,18 @@ function measureTrailingItem(lyricsElement, className) {
|
|
|
1679
1679
|
const bounds = getRelativeLayoutBounds(lyricsElement, element);
|
|
1680
1680
|
return { lyricElement: element, position: bounds.y, height: bounds.height };
|
|
1681
1681
|
}
|
|
1682
|
-
|
|
1682
|
+
// A leading line slower than the one behind closes their gap by distance times progress difference.
|
|
1683
|
+
function lineScrollStaggerScale(lines, activeLineIndex, scrollDistancePx, naturalAdvance) {
|
|
1684
|
+
if (naturalAdvance)
|
|
1685
|
+
return 1;
|
|
1686
|
+
const active = lines[activeLineIndex];
|
|
1687
|
+
const steps = [lines[activeLineIndex - 1], lines[activeLineIndex + 1]]
|
|
1688
|
+
.filter(neighbour => neighbour !== undefined)
|
|
1689
|
+
.map(neighbour => Math.abs(active.position - neighbour.position));
|
|
1690
|
+
const stepPx = steps.length > 0 ? Math.min(...steps) : active.height;
|
|
1691
|
+
return Math.min(1, stepPx / scrollDistancePx);
|
|
1692
|
+
}
|
|
1693
|
+
function prepareLineScrollOffsets(engine, lines, activeLineIndex, scrollDeltaPx, fromScrollTop, toScrollTop, viewportHeight, config, naturalAdvance) {
|
|
1683
1694
|
if (!config.enabled.scroll || activeLineIndex < 0) {
|
|
1684
1695
|
return null;
|
|
1685
1696
|
}
|
|
@@ -1742,12 +1753,16 @@ function prepareLineScrollOffsets(engine, lines, activeLineIndex, scrollDeltaPx,
|
|
|
1742
1753
|
startTranslates = batchResolveLineScrollProperty(engine, items, "translate", item => lineScrollTranslate(item.side, "start", config.lineScroll.differentialEffects), style => normalizedTranslate(style.translate));
|
|
1743
1754
|
endTranslates = batchResolveLineScrollProperty(engine, items, "translate", item => lineScrollTranslate(item.side, "end", config.lineScroll.differentialEffects), style => normalizedTranslate(style.translate));
|
|
1744
1755
|
}
|
|
1756
|
+
const staggerScale = lineScrollStaggerScale(lines, activeLineIndex, scrollDistancePx, naturalAdvance);
|
|
1757
|
+
const activeDurationMs = requests.find(request => request.relativeIndex === 0)?.timing?.durationMs;
|
|
1745
1758
|
return {
|
|
1746
1759
|
items: requests.map((request, requestIndex) => {
|
|
1747
1760
|
const timing = request.timing;
|
|
1748
1761
|
return {
|
|
1749
1762
|
...request.item,
|
|
1750
|
-
durationMs:
|
|
1763
|
+
durationMs: activeDurationMs === undefined
|
|
1764
|
+
? timing.durationMs
|
|
1765
|
+
: activeDurationMs + (timing.durationMs - activeDurationMs) * staggerScale,
|
|
1751
1766
|
startEasing: timing.startEasing,
|
|
1752
1767
|
endEasing: timing.endEasing,
|
|
1753
1768
|
startTranslate: startTranslates ? startTranslates[requestIndex] : defaultStartTranslate,
|
|
@@ -1789,7 +1804,7 @@ function pendingLineScrollMatches(engine, activeLine, fromScrollTop, toScrollTop
|
|
|
1789
1804
|
Math.abs(engine.pendingLineScroll.fromScrollTop - fromScrollTop) <= 2 &&
|
|
1790
1805
|
Math.abs(engine.pendingLineScroll.toScrollTop - toScrollTop) <= 2);
|
|
1791
1806
|
}
|
|
1792
|
-
function commitOrPrepareLineScroll(engine, lines, activeLine, scrollDeltaPx, fromScrollTop, toScrollTop, viewportHeight, config) {
|
|
1807
|
+
function commitOrPrepareLineScroll(engine, lines, activeLine, scrollDeltaPx, fromScrollTop, toScrollTop, viewportHeight, config, naturalAdvance) {
|
|
1793
1808
|
if (pendingLineScrollMatches(engine, activeLine, fromScrollTop, toScrollTop)) {
|
|
1794
1809
|
const pending = engine.pendingLineScroll;
|
|
1795
1810
|
engine.pendingLineScroll = null;
|
|
@@ -1797,16 +1812,16 @@ function commitOrPrepareLineScroll(engine, lines, activeLine, scrollDeltaPx, fro
|
|
|
1797
1812
|
return;
|
|
1798
1813
|
}
|
|
1799
1814
|
dropPendingLineScroll(engine);
|
|
1800
|
-
const plan = prepareLineScrollOffsets(engine, lines, lines.findIndex(line => line.lyricElement === activeLine.lyricElement), scrollDeltaPx, fromScrollTop, toScrollTop, viewportHeight, config);
|
|
1815
|
+
const plan = prepareLineScrollOffsets(engine, lines, lines.findIndex(line => line.lyricElement === activeLine.lyricElement), scrollDeltaPx, fromScrollTop, toScrollTop, viewportHeight, config, naturalAdvance);
|
|
1801
1816
|
if (plan)
|
|
1802
1817
|
startPreparedLineScroll(engine, plan);
|
|
1803
1818
|
}
|
|
1804
|
-
function prepareUpcomingLineScroll(engine, lines, activeLine, scrollDeltaPx, fromScrollTop, toScrollTop, viewportHeight, config) {
|
|
1819
|
+
function prepareUpcomingLineScroll(engine, lines, activeLine, scrollDeltaPx, fromScrollTop, toScrollTop, viewportHeight, config, naturalAdvance) {
|
|
1805
1820
|
if (pendingLineScrollMatches(engine, activeLine, fromScrollTop, toScrollTop))
|
|
1806
1821
|
return;
|
|
1807
1822
|
dropPendingLineScroll(engine);
|
|
1808
1823
|
const activeLineIndex = lines.findIndex(line => line.lyricElement === activeLine.lyricElement);
|
|
1809
|
-
const plan = prepareLineScrollOffsets(engine, lines, activeLineIndex, scrollDeltaPx, fromScrollTop, toScrollTop, viewportHeight, config);
|
|
1824
|
+
const plan = prepareLineScrollOffsets(engine, lines, activeLineIndex, scrollDeltaPx, fromScrollTop, toScrollTop, viewportHeight, config, naturalAdvance);
|
|
1810
1825
|
if (plan) {
|
|
1811
1826
|
engine.pendingLineScroll = {
|
|
1812
1827
|
plan,
|
|
@@ -2332,6 +2347,12 @@ export function tickView(engine, currentTime, options) {
|
|
|
2332
2347
|
}
|
|
2333
2348
|
const timeJumped = Math.abs(currentTime - playbackClock.lastTime - (eventCreationTime - playbackClock.lastEventCreationTime) / 1000) >
|
|
2334
2349
|
TIME_JUMP_THRESHOLD;
|
|
2350
|
+
// Without a player snapshot the reading is the media clock, which runs backwards only on a seek, so a
|
|
2351
|
+
// loop shorter than the jump threshold still re-arms lines. A snapshot host's extrapolated clock is
|
|
2352
|
+
// pulled back by every correction, so it is left to the threshold.
|
|
2353
|
+
const mediaSteppedBack = eventCreationTime === NO_PLAYER_SNAPSHOT &&
|
|
2354
|
+
isPlaying &&
|
|
2355
|
+
currentTime < playbackClock.lastTime - CLOCK_RESYNC_THRESHOLD_S;
|
|
2335
2356
|
if (timeJumped)
|
|
2336
2357
|
dropPendingLineScroll(engine);
|
|
2337
2358
|
playbackClock.lastTime = currentTime;
|
|
@@ -2444,7 +2465,7 @@ export function tickView(engine, currentTime, options) {
|
|
|
2444
2465
|
lineData.isAnimating = false; // reset the animation against current media time
|
|
2445
2466
|
}
|
|
2446
2467
|
// Lead-in animations have no timing sample for the drift check, so a jump while playing must reset them.
|
|
2447
|
-
if (timeJumped && isPlaying && lineData.isAnimating)
|
|
2468
|
+
if (((timeJumped && isPlaying) || mediaSteppedBack) && lineData.isAnimating)
|
|
2448
2469
|
resetLineAnimationState(lineData);
|
|
2449
2470
|
updateWordStates(lineData, currentTime);
|
|
2450
2471
|
const nativeTimingSample = lineNativeTimingSample(lineData, currentTime);
|
|
@@ -2634,6 +2655,8 @@ export function tickView(engine, currentTime, options) {
|
|
|
2634
2655
|
}
|
|
2635
2656
|
}
|
|
2636
2657
|
const timeUntilUpcomingScrollMs = (lastActiveLyric.time - lyricScrollTime) * 1000;
|
|
2658
|
+
// Only a scroll from where the engine itself left the view keeps the theme's full stagger.
|
|
2659
|
+
const naturalAdvance = !timeJumped && !engine.wasUserScrolling && engine.scrollPos >= 0 && Math.abs(scrollTop - engine.scrollPos) <= 2;
|
|
2637
2660
|
if (smoothScroll &&
|
|
2638
2661
|
animationConfig.enabled.scroll &&
|
|
2639
2662
|
!newLyricSelected &&
|
|
@@ -2643,7 +2666,7 @@ export function tickView(engine, currentTime, options) {
|
|
|
2643
2666
|
!engine.lastScrollElements.includes(lastActiveLyric) &&
|
|
2644
2667
|
Math.abs(scrollTop - scrollPos) > 2) {
|
|
2645
2668
|
updateVisibleLyricWillChange(engine, lines, scrollTop, scrollPos, tabRendererHeight);
|
|
2646
|
-
prepareUpcomingLineScroll(engine, getLineScrollItems(engine, lines), lastActiveLyric, scrollPos - scrollTop, scrollTop, scrollPos, tabRendererHeight, animationConfig);
|
|
2669
|
+
prepareUpcomingLineScroll(engine, getLineScrollItems(engine, lines), lastActiveLyric, scrollPos - scrollTop, scrollTop, scrollPos, tabRendererHeight, animationConfig, naturalAdvance);
|
|
2647
2670
|
}
|
|
2648
2671
|
if (engine.wasUserScrolling || newLyricSelected) {
|
|
2649
2672
|
// Remember future lines only when their group is committed, so they cannot scroll
|
|
@@ -2658,7 +2681,7 @@ export function tickView(engine, currentTime, options) {
|
|
|
2658
2681
|
if (animationConfig.enabled.scroll) {
|
|
2659
2682
|
updateVisibleLyricWillChange(engine, lines, scrollTop, scrollPos, tabRendererHeight);
|
|
2660
2683
|
const lineScrollItems = getLineScrollItems(engine, lines);
|
|
2661
|
-
commitOrPrepareLineScroll(engine, lineScrollItems, lastActiveLyric, scrollDeltaPx, scrollTop, scrollPos, tabRendererHeight, animationConfig);
|
|
2684
|
+
commitOrPrepareLineScroll(engine, lineScrollItems, lastActiveLyric, scrollDeltaPx, scrollTop, scrollPos, tabRendererHeight, animationConfig, naturalAdvance);
|
|
2662
2685
|
}
|
|
2663
2686
|
}
|
|
2664
2687
|
else {
|