Menu: improve animation for top-right
All checks were successful
/ depoly (push) Successful in 1m18s
All checks were successful
/ depoly (push) Successful in 1m18s
This commit is contained in:
parent
bafa8f4e24
commit
10b517bceb
3 changed files with 151 additions and 29 deletions
|
@ -53,3 +53,145 @@ export function useHeroSignal(
|
|||
return [() => undefined, () => undefined];
|
||||
}
|
||||
}
|
||||
|
||||
export function animateRollOutFromTop(
|
||||
root: HTMLElement,
|
||||
options?: Omit<KeyframeAnimationOptions, "duration">,
|
||||
) {
|
||||
const overflow = root.style.overflow;
|
||||
root.style.overflow = "hidden";
|
||||
|
||||
const { height } = root.getBoundingClientRect();
|
||||
|
||||
const opts = Object.assign(
|
||||
{
|
||||
duration: Math.floor((height / 1600) * 1000),
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
const animation = root.animate(
|
||||
{
|
||||
height: ["0px", `${height}px`],
|
||||
},
|
||||
opts,
|
||||
);
|
||||
|
||||
const restore = () => (root.style.overflow = overflow);
|
||||
|
||||
animation.addEventListener("finish", restore);
|
||||
animation.addEventListener("cancel", restore);
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
|
||||
export function animateRollInFromBottom(
|
||||
root: HTMLElement,
|
||||
options?: Omit<KeyframeAnimationOptions, "duration">,
|
||||
) {
|
||||
const overflow = root.style.overflow;
|
||||
root.style.overflow = "hidden";
|
||||
|
||||
const { height } = root.getBoundingClientRect();
|
||||
|
||||
const opts = Object.assign(
|
||||
{
|
||||
duration: Math.floor((height / 1600) * 1000),
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
const animation = root.animate(
|
||||
{
|
||||
height: [`${height}px`, "0px"],
|
||||
},
|
||||
opts,
|
||||
);
|
||||
|
||||
const restore = () => (root.style.overflow = overflow);
|
||||
|
||||
animation.addEventListener("finish", restore);
|
||||
animation.addEventListener("cancel", restore);
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
export function animateGrowFromTopRight(
|
||||
root: HTMLElement,
|
||||
options?: KeyframeAnimationOptions,
|
||||
) {
|
||||
const transformOrigin = root.style.transformOrigin;
|
||||
root.style.transformOrigin = "top right";
|
||||
|
||||
const { width, height } = root.getBoundingClientRect();
|
||||
|
||||
const durationX = Math.floor((height / 1600) * 1000);
|
||||
const durationY = Math.floor((width / 1600) * 1000);
|
||||
|
||||
// finds the offset for the center frame,
|
||||
// it will stops at the (minDuration / maxDuration)%
|
||||
const minDuration = Math.min(durationX, durationY);
|
||||
const maxDuration = Math.max(durationX, durationY);
|
||||
|
||||
const centerOffset = minDuration / maxDuration;
|
||||
|
||||
const keyframes = [
|
||||
{ transform: "scaleX(0)", opacity: 0, height: "0px", offset: 0 },
|
||||
{
|
||||
transform: `scaleX(${minDuration === durationX ? "1" : centerOffset})`,
|
||||
height: `${(minDuration === durationY ? 1 : centerOffset) * height}px`,
|
||||
offset: centerOffset,
|
||||
opacity: 1,
|
||||
},
|
||||
{ transform: "scaleX(1)", height: `${height}px`, offset: 1 },
|
||||
];
|
||||
|
||||
const animation = root.animate(
|
||||
keyframes,
|
||||
{ ...options, duration: maxDuration },
|
||||
);
|
||||
|
||||
const restore = () => {
|
||||
root.style.transformOrigin = transformOrigin;
|
||||
};
|
||||
|
||||
animation.addEventListener("cancel", restore);
|
||||
animation.addEventListener("finish", restore);
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
export function animateShrinkToTopRight(
|
||||
root: HTMLElement,
|
||||
options?: KeyframeAnimationOptions,
|
||||
) {
|
||||
const overflow = root.style.overflow;
|
||||
root.style.overflow = "hidden";
|
||||
const transformOrigin = root.style.transformOrigin;
|
||||
root.style.transformOrigin = "top right";
|
||||
|
||||
const { width, height } = root.getBoundingClientRect();
|
||||
|
||||
const duration = Math.floor(
|
||||
Math.max((width / 1600) * 1000, (height / 1600) * 1000),
|
||||
);
|
||||
|
||||
const animation = root.animate(
|
||||
{
|
||||
transform: ["scale(1)", "scale(0.5)"],
|
||||
opacity: [1, 0],
|
||||
},
|
||||
{ ...options, duration },
|
||||
);
|
||||
|
||||
const restore = () => {
|
||||
root.style.overflow = overflow;
|
||||
root.style.transformOrigin = transformOrigin;
|
||||
};
|
||||
|
||||
animation.addEventListener("cancel", restore);
|
||||
animation.addEventListener("finish", restore);
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue