feat(story): build procedural notebook animation
This commit is contained in:
1 parent
f3ed9da777
commit
b079afdd73
9 files changed
+360
-213
No files matched your search
@@ -23,12 +23,9 @@ const OPEN_ANGLE = 112;
|
||||
const BROWSE_START = 0.44;
|
||||
const BROWSE_END = 0.78;
|
||||
const HOLD_END = 0.87;
|
||||
const CURSOR_POINTS = [
|
||||
{ x: 0.26, y: 0.68 },
|
||||
{ x: 0.58, y: 0.32 },
|
||||
{ x: 0.74, y: 0.72 },
|
||||
{ x: 0.38, y: 0.28 },
|
||||
];
|
||||
const CLOSE_LID_START = 0.9;
|
||||
const TAB_CLICK_Y = 0.3;
|
||||
const PARK = { x: 0.5, y: 0.95 };
|
||||
|
||||
function clamp(value: number, min: number, max: number): number {
|
||||
return Math.min(Math.max(value, min), max);
|
||||
@@ -77,6 +74,11 @@ function getActiveTabIndex(
|
||||
return clamp(Math.floor(browseProgress * tabCount), 0, tabCount - 1);
|
||||
}
|
||||
|
||||
function tabCenterX(index: number, tabCount: number): number {
|
||||
if (tabCount < 1) return PARK.x;
|
||||
return (index + 0.5) / tabCount;
|
||||
}
|
||||
|
||||
function getCursorPoint(
|
||||
progress: number,
|
||||
phase: NotebookPhase,
|
||||
@@ -86,27 +88,30 @@ function getCursorPoint(
|
||||
if (phase === "cursor-in") {
|
||||
const cursorProgress = (progress - 0.34) / 0.1;
|
||||
return {
|
||||
x: interpolate(0.06, 0.26, cursorProgress),
|
||||
y: interpolate(0.88, 0.68, cursorProgress),
|
||||
x: interpolate(PARK.x, tabCenterX(0, tabCount), cursorProgress),
|
||||
y: interpolate(PARK.y, TAB_CLICK_Y, cursorProgress),
|
||||
};
|
||||
}
|
||||
|
||||
if (activeTabIndex < 0) {
|
||||
return { x: 0.06, y: 0.88 };
|
||||
return { ...PARK };
|
||||
}
|
||||
|
||||
const target = CURSOR_POINTS[activeTabIndex % CURSOR_POINTS.length];
|
||||
const target = { x: tabCenterX(activeTabIndex, tabCount), y: TAB_CLICK_Y };
|
||||
if (phase !== "browse" || activeTabIndex === 0) return target;
|
||||
|
||||
const browseProgress =
|
||||
(progress - BROWSE_START) / (BROWSE_END - BROWSE_START);
|
||||
const slotProgress = browseProgress * tabCount - activeTabIndex;
|
||||
const previous = CURSOR_POINTS[(activeTabIndex - 1) % CURSOR_POINTS.length];
|
||||
const previous = {
|
||||
x: tabCenterX(activeTabIndex - 1, tabCount),
|
||||
y: TAB_CLICK_Y,
|
||||
};
|
||||
const moveProgress = clamp(slotProgress / 0.36, 0, 1);
|
||||
|
||||
return {
|
||||
x: interpolate(previous.x, target.x, moveProgress),
|
||||
y: interpolate(previous.y, target.y, moveProgress),
|
||||
y: target.y,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -158,11 +163,13 @@ export function getNotebookFrame(
|
||||
const lidAngle = isOpening
|
||||
? interpolate(0, OPEN_ANGLE, (normalizedProgress - 0.1) / 0.15)
|
||||
: isClosing
|
||||
? interpolate(
|
||||
OPEN_ANGLE,
|
||||
0,
|
||||
(normalizedProgress - HOLD_END) / (1 - HOLD_END),
|
||||
)
|
||||
? normalizedProgress < CLOSE_LID_START
|
||||
? OPEN_ANGLE
|
||||
: interpolate(
|
||||
OPEN_ANGLE,
|
||||
0,
|
||||
(normalizedProgress - CLOSE_LID_START) / (1 - CLOSE_LID_START),
|
||||
)
|
||||
: normalizedProgress >= 0.25
|
||||
? OPEN_ANGLE
|
||||
: 0;
|
||||
@@ -171,7 +178,11 @@ export function getNotebookFrame(
|
||||
: normalizedProgress >= 0.34 && !isClosing
|
||||
? 1
|
||||
: isClosing
|
||||
? interpolate(1, 0, (normalizedProgress - HOLD_END) / (1 - HOLD_END))
|
||||
? interpolate(
|
||||
1,
|
||||
0,
|
||||
(normalizedProgress - HOLD_END) / (CLOSE_LID_START - HOLD_END),
|
||||
)
|
||||
: 0;
|
||||
const deviceOpacity = isApproach
|
||||
? interpolate(0, 1, normalizedProgress / 0.1)
|
||||
|
||||
Reference in new issue
Block a user