TootList: add hero animation

This commit is contained in:
thislight 2024-11-17 17:37:58 +08:00
parent 1641f3e75b
commit 6879eb5292
No known key found for this signature in database
GPG key ID: FCFE5192241CCD4E

View file

@ -13,7 +13,6 @@ import { useDefaultSession } from "../masto/clients";
import { useHeroSource } from "../platform/anim";
import { HERO as BOTTOM_SHEET_HERO } from "../material/BottomSheet";
import { setCache as setTootBottomSheetCache } from "./TootBottomSheet";
import { useNavigate } from "@solidjs/router";
import RegularToot, {
findElementActionable,
findRootToot,
@ -21,6 +20,21 @@ import RegularToot, {
import cardStyle from "../material/cards.module.css";
import type { ThreadNode } from "../masto/timelines";
import { useNavigator } from "../platform/StackedRouter";
import { ANIM_CURVE_STD } from "../material/theme";
function durationOf(rect0: DOMRect, rect1: DOMRect) {
const distancelt = Math.sqrt(
Math.pow(Math.abs(rect0.top - rect1.top), 2) +
Math.pow(Math.abs(rect0.left - rect1.left), 2),
);
const distancerb = Math.sqrt(
Math.pow(Math.abs(rect0.bottom - rect1.bottom), 2) +
Math.pow(Math.abs(rect0.right - rect1.right), 2),
);
const distance = distancelt + distancerb;
const duration = distance / 1.6;
return duration;
}
function positionTootInThread(index: number, threadLength: number) {
if (index === 0) {
@ -41,7 +55,7 @@ const TootList: Component<{
const session = useDefaultSession();
const heroSrc = useHeroSource();
const [expandedThreadId, setExpandedThreadId] = createSignal<string>();
const {push} = useNavigator();
const { push } = useNavigator();
const onBookmark = async (status: mastodon.v1.Status) => {
const client = session()?.client;
@ -100,7 +114,7 @@ const TootList: Component<{
const openFullScreenToot = (
toot: mastodon.v1.Status,
srcElement?: HTMLElement,
srcElement: HTMLElement,
reply?: boolean,
) => {
const p = session()?.account;
@ -116,12 +130,55 @@ const TootList: Component<{
const acct = `${inf.username}@${p.site}`;
setTootBottomSheetCache(acct, toot);
push(`/${encodeURIComponent(acct)}/toot/${toot.id}`, {
state: reply
? {
tootReply: true,
}
: undefined,
animateOpen(element) {
const rect0 = srcElement.getBoundingClientRect(); // the start rect
const rect1 = element.getBoundingClientRect(); // the end rect
const duration = durationOf(rect0, rect1);
const keyframes = {
top: [`${rect0.top}px`, `${rect1.top}px`],
bottom: [`${rect0.bottom}px`, `${rect1.bottom}px`],
left: [`${rect0.left}px`, `${rect1.left}px`],
right: [`${rect0.right}px`, `${rect1.right}px`],
height: [`${rect0.height}px`, `${rect1.height}px`],
margin: 0,
};
srcElement.style.visibility = "hidden";
const animation = element.animate(keyframes, {
duration,
easing: ANIM_CURVE_STD,
});
return animation;
},
animateClose(element) {
const rect0 = element.getBoundingClientRect(); // the start rect
const rect1 = srcElement.getBoundingClientRect(); // the end rect
const duration = durationOf(rect0, rect1);
const keyframes = {
top: [`${rect0.top}px`, `${rect1.top}px`],
bottom: [`${rect0.bottom}px`, `${rect1.bottom}px`],
left: [`${rect0.left}px`, `${rect1.left}px`],
right: [`${rect0.right}px`, `${rect1.right}px`],
height: [`${rect0.height}px`, `${rect1.height}px`],
margin: 0,
};
srcElement.style.visibility = "";
const animation = element.animate(keyframes, {
duration,
easing: ANIM_CURVE_STD,
});
return animation;
},
});
};