cohost/html/crumble.tsx
2023-09-07 22:18:13 -04:00

120 lines
3.7 KiB
TypeScript

import { ComponentChildren } from "preact";
import { css, render_and_copy } from "./common.tsx";
// combine a shake with a fall
// fall should be more delayed than shake
// we want outliers (a few letters falling before than others)
// exponentials should do
export type DelayFn = (_: number) => number;
// sue me v (please do actually this is a bit ridiculous)
const default_shaky_delay /**/ = (x: number) => 10 + 20 * x;
const default_fall_delay /* */ = (x: number) => 15 + 30 * x;
// exporting these in case they turn out to be useful
export const Shaky = ({
children,
delay = 0,
}: {
children: ComponentChildren;
delay?: number;
}) => (
<span
style={{
transform: css.transform(css.translate(css.px(-1), css.px(-1))),
animation: `0.2s spin alternate-reverse linear ${delay.toFixed(
2
)}s infinite`,
display: css.inline_block,
}}
>
{children}
</span>
);
// direction should be random but that doesn't need to be as custo
// well should it
// i think i'll try without that first
// a slow fall is fun
// i could have some weird hack where there's another copy that's hidden but that seems like the wrong way to do it
// i think the best way to do it is jump-hackery (jump 0s in to the start
// (which is 0 displacement when reversed)), then wait, then jump to the real animation
// ah but then how to do linear stuff without a million steps
// methinks yet more nesting unfortunately (yep)
// long enough that most won't watch it till the end i hope
// i clearly did my physics wrong
// d = vt -> t = d/v right?
const fall_dy = 4113;
const fall_v = 10;
export const Fall = ({
children,
delay = 0,
}: {
children: ComponentChildren;
delay?: number;
}) => (
<span
style={{
transform: css.transform(css.translateY(css.rem(fall_dy))),
animation: `0s steps(1, jump-start) spin`,
display: css.inline_block,
}}
>
<span
style={{
transform: css.transform(css.translateY(css.rem(-fall_dy))),
// making the transform so big makes timing a pain lol
animation: `${(fall_dy / fall_v).toFixed(
2
)}s ease-in ${delay.toFixed(2)}s 1 spin`,
display: css.inline_block,
}}
class="bla"
>
{children}
</span>
</span>
);
const msg = `
i haven't seen this on other blogs, but some of the posts on mine seem to be kinda unstable?
if that makes sense?
like, sometimes i see them shake, and i swear i saw some letters fall, not to mention the terrible line-wrapping
i know i'm a (convicted?) css criminal, so i'm thinking that this might just be the w3 gods punishing me.
so. yeah. if you see anything like that on any of my posts, let me know
`.trim();
// should probably do it word wise so they don't break
// where did the cool bug go???
export const Crumble = ({
msg,
shaky_delay_fn = default_shaky_delay,
fall_delay_fn = default_fall_delay,
}: {
msg: string;
shaky_delay_fn?: DelayFn;
fall_delay_fn?: DelayFn;
}) => (
<div>
{msg.split("").map(c => {
if (/[^\s]/.test(c)) {
const seed = Math.random();
const fall_delay = fall_delay_fn(seed);
return (
<Fall delay={fall_delay}>
<Shaky delay={shaky_delay_fn(seed)}>{c}</Shaky>
</Fall>
);
}
if (c == "\n") return <br />;
return c;
})}
</div>
);
render_and_copy(<Crumble msg={msg} />);
// i like the almost comical slowness. send it