BottomSheet: move slides animations to platform

This commit is contained in:
thislight 2024-11-03 17:36:03 +08:00
parent 10b517bceb
commit b61012f12b
No known key found for this signature in database
GPG key ID: FCFE5192241CCD4E
2 changed files with 121 additions and 33 deletions

View file

@ -195,3 +195,105 @@ export function animateShrinkToTopRight(
return animation;
}
// Contribution to the animation speed:
// - the screen size: mobiles should have longer transition,
// the transition time should be longer as the travelling distance longer,
// but it's not linear. The larger screen should have higher velocity,
// to avoid the transition is too long.
// As the screen larger, on desktops, the transition should be simpler and
// signficantly faster.
// On much smaller screens, like wearables, the transition should be shorter
// than on mobiles.
// - Animation complexity: On mobile:
// - large, complex, full-screen transitions may have longer durations, over 375ms
// - entering screen over 225ms
// - leaving screen over 195ms
function transitionSpeedForEnter(innerWidth: number) {
if (innerWidth < 300) {
return 2.4;
} else if (innerWidth < 560) {
return 1.6;
} else if (innerWidth < 1200) {
return 2.4;
} else {
return 2.55;
}
}
function transitionSpeedForLeave(innerWidth: number) {
if (innerWidth < 300) {
return 2.8;
} else if (innerWidth < 560) {
return 1.96;
} else if (innerWidth < 1200) {
return 2.8;
} else {
return 2.55;
}
}
export function animateSlideInFromRight(
root: HTMLElement,
options?: Omit<KeyframeAnimationOptions, "duration">,
) {
const { left } = root.getBoundingClientRect();
const { innerWidth } = window;
const oldOverflow = document.body.style.overflow;
document.body.style.overflow = "hidden";
const distance = Math.abs(left - innerWidth);
const duration = Math.floor(distance / transitionSpeedForEnter(innerWidth));
const opts = Object.assign({ duration }, options);
const animation = root.animate(
{
left: [`${innerWidth}px`, `${left}px`],
},
opts,
);
const restore = () => {
document.body.style.overflow = oldOverflow;
};
animation.addEventListener("cancel", restore);
animation.addEventListener("finish", restore);
return animation;
}
export function animateSlideOutToRight(
root: HTMLElement,
options?: Omit<KeyframeAnimationOptions, "duration">,
) {
const { left } = root.getBoundingClientRect();
const { innerWidth } = window;
const oldOverflow = document.body.style.overflow;
document.body.style.overflow = "hidden";
const distance = Math.abs(left - innerWidth);
const duration = Math.floor(distance / transitionSpeedForLeave(innerWidth));
const opts = Object.assign({ duration }, options);
const animation = root.animate(
{
left: [`${left}px`, `${innerWidth}px`],
},
opts,
);
const restore = () => {
document.body.style.overflow = oldOverflow;
};
animation.addEventListener("cancel", restore);
animation.addEventListener("finish", restore);
return animation;
}