cohost/html/image-macro.tsx

229 lines
6.5 KiB
TypeScript
Raw Normal View History

import { Main, DragResizableImage, render_and_copy, n_of } from "./common.tsx";
2024-01-27 22:22:43 -05:00
// new idea! "make your own image macro" scrollable background of various le classic meme images (imgflip)
// + images (yes, images; nobody has impact installed)
// nah. let's just do white + text-shadow
const base_url = "https://static.pyrope.net/imgflip/";
const urls = [
"aggressive-right-turn.png",
"aliens.png",
"always-has-been.png",
"balloon.png",
"batman-slapping-robin.png",
"bike-self-sabotage.png",
"buff-doge-vs-cheems.png",
"cefqrn.png",
"change-my-mind.png",
"chuck-norris.png",
"despicable-plan.png",
"distracted-boyfriend.png",
"drake.png",
"everywhere-everywhere.png",
"evil-kermit.png",
"expanding-brain.png",
"girl-smile-fire.png",
"heinous-suggestion.png",
"hide-the-pain-harold.png",
"i-am-once-again-asking.png",
"if-i-had-one.png",
"is-this-a.png",
"not-sure-if.png",
"one-does-not-simply.png",
"or-draw-25.png",
"panik-kalm-panik.png",
"psycholonials-reference.png",
"rock-the-dwayne-johnson-driving.png",
"same-picture.png",
"scroll-of-truth.png",
"slam-button.png",
"STRONG-handshake.png",
"success-kid.png",
"tap-head.png",
"thinking-about-other-women.png",
"this-is-fine.png",
"two-buttons.png",
"waiting-guy.png",
"waiting-skeleton.png",
"who-killed.png",
"woman-yelling-at-cat.png",
"you-get-a.png",
].map(x => base_url + x);
2023-08-19 20:30:42 -04:00
2024-01-27 22:22:43 -05:00
const Word = ({
children,
left = "0px",
top = "0px",
}: {
children: string;
left?: string;
top?: string;
}) => (
2023-08-19 20:30:42 -04:00
<div
style={{
2024-01-27 22:22:43 -05:00
position: "absolute",
resize: "both",
minWidth: "max-content",
minHeight: "fit-content",
width: left,
height: top,
overflow: "hidden",
display: "flex",
// justifyContent: "right",
// alignContent: "bottom",
2023-08-19 20:30:42 -04:00
}}
>
2024-01-27 22:22:43 -05:00
<h1
style={{
color: "white",
textShadow: "0px 0px 2px black",
margin: "auto 0 0 auto",
}}
>
{children}
</h1>
2023-08-19 20:30:42 -04:00
</div>
);
2024-01-27 22:22:43 -05:00
// alright, doing it the right way (https://cohost.org/blackle/post/38921-alright-cohost-it) is too hard.
// let's cheat.
// if we aren't random, and instead distribute things such that the initial setup has the least covered
// ehhhhhhhhhhhhhhhhhh
// sighhhhh let's just do it right
// generate the stupid freaking impact font
// use it as a background image
// ughhhhhh
// oo i know i'll make one image in photopea and just clip it
// that should work and be easy fingers crossed
// that'll actually be way harder to adapt lel
// ughhhh am i going to have to pull out that crappy library
// AND download an impact font
// (yes)
// tl;dr i can still use this scattering
// imagescript can't do the shadow we need (thank goodness)
// maybe imagemagick + photopea then
// i got it (KISS): photopea -> split on command line -> reference by url
// that should be workable
const words = {
THE: 6,
HOMESTUCK: 3,
MEME: 4,
IS: 4,
EGGBUG: 4,
WHEN: 2,
YOU: 5,
SUS: 1,
IMPOSTER: 1,
ME: 3,
ALIEN: 1,
ARE: 3,
A: 4,
BOTTOM: 2,
TOP: 2,
TEXT: 4,
"?": 3,
"!": 3,
NO: 3,
YES: 3,
COHOST: 2,
MEHBARK: 2,
WEBARK: 2,
THIS: 2,
POST: 2,
SUCK: 2,
"CHUCK NORRIS": 2,
FOR: 2,
S: 4,
GET: 2,
} satisfies Record<string, number>;
console.log(
`yikes. there are ${
Object.keys(words).length
} unique words and ${Object.values(words).reduce(
(a, b) => a + b
)} words in total`
);
// Object.keys(words).forEach(w => console.log(w))
const text_img_url = (text: string) =>
`https://static.pyrope.net/meme-text/${text}.png`;
const TEXT_HEIGHT = 55;
const decoder = new TextDecoder();
// crazy inefficient but idc
const get_text_width = (text: string): number =>
+decoder.decode(
new Deno.Command("identify", {
args: ["-format", "%w", `static/meme-text/${text}.png`],
}).outputSync().stdout
);
const ScatteredWords = ({ children }: { children: Record<string, number> }) => (
2024-01-27 22:22:43 -05:00
<>
{...Object.entries(children).flatMap(([text, count]) =>
// feels pretty snazzy ngl
n_of(Math.ceil(count), () => (
<DragResizableImage
top={Math.random() * 413}
left={Math.random() * 612}
url={text_img_url(text)}
height={TEXT_HEIGHT}
width={get_text_width(text)}
indicator_opacity={0.2}
/>
)).map(f => f())
)}
2024-01-27 22:22:43 -05:00
</>
);
render_and_copy(
<>
<Main
style={{ width: "100%", aspectRatio: "1" }}
aria-described-by="user-content-meme-description"
>
<ScatteredWords>{words}</ScatteredWords>
2024-01-27 22:22:43 -05:00
<div
style={{
display: "flex",
overflow: "scroll",
alignItems: "center",
gap: "1rem",
}}
>
{...urls.map(u => (
<img
src={u}
style={{
maxHeight: "50vh",
outline: "1px solid black",
}}
/>
))}
</div>
</Main>
<p style={{ fontSize: "0px" }}>
a horizontally scrollable list of memes with draggable words that
look like a knockoff of impact font. if you want a better and
(hopefully) more accessible version, visit imgflip.com. all of the
memes are taken from there anyway
</p>
notes as per usual i do this all th etime:
<ul>
<li>
dragresizing taken <em>entirely</em> from @blackle's excellent
post: https://cohost.org/blackle/post/38921-alright-cohost-it
</li>
<li>
you have to get the very center to drag. @blackle put an
indicator but i made it optional and turned it off! sorry!
aesthetics! (edit: turned em back on. character growth! i did
turn the opacity down just a squidge. idk. it's late!)
</li>
<li>
i probably could have turned the resizing off too, but, you
know, it's very funny
</li>
</ul>
2024-01-27 22:22:43 -05:00
</>
);