TootList: add hero animation
This commit is contained in:
parent
1641f3e75b
commit
6879eb5292
1 changed files with 65 additions and 8 deletions
|
@ -13,7 +13,6 @@ import { useDefaultSession } from "../masto/clients";
|
||||||
import { useHeroSource } from "../platform/anim";
|
import { useHeroSource } from "../platform/anim";
|
||||||
import { HERO as BOTTOM_SHEET_HERO } from "../material/BottomSheet";
|
import { HERO as BOTTOM_SHEET_HERO } from "../material/BottomSheet";
|
||||||
import { setCache as setTootBottomSheetCache } from "./TootBottomSheet";
|
import { setCache as setTootBottomSheetCache } from "./TootBottomSheet";
|
||||||
import { useNavigate } from "@solidjs/router";
|
|
||||||
import RegularToot, {
|
import RegularToot, {
|
||||||
findElementActionable,
|
findElementActionable,
|
||||||
findRootToot,
|
findRootToot,
|
||||||
|
@ -21,6 +20,21 @@ import RegularToot, {
|
||||||
import cardStyle from "../material/cards.module.css";
|
import cardStyle from "../material/cards.module.css";
|
||||||
import type { ThreadNode } from "../masto/timelines";
|
import type { ThreadNode } from "../masto/timelines";
|
||||||
import { useNavigator } from "../platform/StackedRouter";
|
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) {
|
function positionTootInThread(index: number, threadLength: number) {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
|
@ -100,7 +114,7 @@ const TootList: Component<{
|
||||||
|
|
||||||
const openFullScreenToot = (
|
const openFullScreenToot = (
|
||||||
toot: mastodon.v1.Status,
|
toot: mastodon.v1.Status,
|
||||||
srcElement?: HTMLElement,
|
srcElement: HTMLElement,
|
||||||
reply?: boolean,
|
reply?: boolean,
|
||||||
) => {
|
) => {
|
||||||
const p = session()?.account;
|
const p = session()?.account;
|
||||||
|
@ -116,12 +130,55 @@ const TootList: Component<{
|
||||||
|
|
||||||
const acct = `${inf.username}@${p.site}`;
|
const acct = `${inf.username}@${p.site}`;
|
||||||
setTootBottomSheetCache(acct, toot);
|
setTootBottomSheetCache(acct, toot);
|
||||||
|
|
||||||
push(`/${encodeURIComponent(acct)}/toot/${toot.id}`, {
|
push(`/${encodeURIComponent(acct)}/toot/${toot.id}`, {
|
||||||
state: reply
|
animateOpen(element) {
|
||||||
? {
|
const rect0 = srcElement.getBoundingClientRect(); // the start rect
|
||||||
tootReply: true,
|
const rect1 = element.getBoundingClientRect(); // the end rect
|
||||||
}
|
|
||||||
: undefined,
|
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;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue