meme: DONE ENOUGH. THIS POST SUCKS BUT IS GREAT
|
@ -118,6 +118,15 @@
|
||||||
"https://deno.land/x/imagescript@1.2.15/v2/ops/resize.mjs": "814e78ebce8eaf8f1f918688db7b52a141405e06a36ed4b25d04413d69e7d17b",
|
"https://deno.land/x/imagescript@1.2.15/v2/ops/resize.mjs": "814e78ebce8eaf8f1f918688db7b52a141405e06a36ed4b25d04413d69e7d17b",
|
||||||
"https://deno.land/x/imagescript@1.2.15/v2/ops/rotate.mjs": "a1b65616717bd2eed8db406affea3263b4674dada46b56441ef38167a187455d",
|
"https://deno.land/x/imagescript@1.2.15/v2/ops/rotate.mjs": "a1b65616717bd2eed8db406affea3263b4674dada46b56441ef38167a187455d",
|
||||||
"https://deno.land/x/imagescript@1.2.15/v2/util/mem.mjs": "4968d400dae069b4bf0ef4767c1802fd2cc7d15d90eda4cfadf5b4cd19b96c6d",
|
"https://deno.land/x/imagescript@1.2.15/v2/util/mem.mjs": "4968d400dae069b4bf0ef4767c1802fd2cc7d15d90eda4cfadf5b4cd19b96c6d",
|
||||||
|
"https://deno.land/x/imagescript@1.2.9/ImageScript.js": "4f6f9c1542dd55b91dfdd01d1b2e8e5ff1eb3b3a7a4a30bdd5ff673d9aecab45",
|
||||||
|
"https://deno.land/x/imagescript@1.2.9/utils/buffer.js": "952cb1beb8827e50a493a5d1f29a4845e8c648789406d389dd51f51205ba02d8",
|
||||||
|
"https://deno.land/x/imagescript@1.2.9/utils/crc32.js": "573d6222b3605890714ebc374e687ec2aa3e9a949223ea199483e47ca4864f7d",
|
||||||
|
"https://deno.land/x/imagescript@1.2.9/utils/png.js": "fbed9117e0a70602645d70df9c103ff6e79c03e987bd5c1685dcb4200729b6de",
|
||||||
|
"https://deno.land/x/imagescript@1.2.9/utils/wasm/font.js": "ae4e8b7b6e6e9a30250c5f89e8fbb92d237f69d80ff84cd80c95d9a04163e714",
|
||||||
|
"https://deno.land/x/imagescript@1.2.9/utils/wasm/gif.js": "100fbd424a828a76ce90e4f5c282d42e0ab83518908a75839d5ded52bb795340",
|
||||||
|
"https://deno.land/x/imagescript@1.2.9/utils/wasm/jpeg.js": "da660e827fa45a85ee63aafa38dceb031dbd8988162bf730ace8d6135d842413",
|
||||||
|
"https://deno.land/x/imagescript@1.2.9/utils/wasm/svg.js": "f7d8827fa8dc4aa9b1027374a87ae658da4bdd46048c66c01d909291d1cf132a",
|
||||||
|
"https://deno.land/x/imagescript@1.2.9/utils/wasm/zlib.js": "63060a9aabee087929eb01d9e8b75b3ddc94a846a929a81d4456ed9b54d72671",
|
||||||
"https://esm.sh/preact-render-to-string@5.2.0?external=preact": "d68df08425ff945f8b2872d784d587c6588f9f6369e553758d254477bfc95818",
|
"https://esm.sh/preact-render-to-string@5.2.0?external=preact": "d68df08425ff945f8b2872d784d587c6588f9f6369e553758d254477bfc95818",
|
||||||
"https://esm.sh/preact@10.16.0": "5229650cdac537f87cae81d5001e88d4e7a38cc7e77be978961d2897a733117d",
|
"https://esm.sh/preact@10.16.0": "5229650cdac537f87cae81d5001e88d4e7a38cc7e77be978961d2897a733117d",
|
||||||
"https://esm.sh/preact@10.16.0/jsx-runtime?dts": "9e67b64a5b48299c77d30bffc213735fdcf4b3b5d4ad8ff8d4136f246de5fa34",
|
"https://esm.sh/preact@10.16.0/jsx-runtime?dts": "9e67b64a5b48299c77d30bffc213735fdcf4b3b5d4ad8ff8d4136f246de5fa34",
|
||||||
|
|
|
@ -386,6 +386,7 @@ export const DragResizableImage = ({
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
indicator = true,
|
indicator = true,
|
||||||
|
indicator_opacity = 0.3,
|
||||||
}: {
|
}: {
|
||||||
url: string;
|
url: string;
|
||||||
top: number;
|
top: number;
|
||||||
|
@ -393,6 +394,7 @@ export const DragResizableImage = ({
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
indicator?: boolean;
|
indicator?: boolean;
|
||||||
|
indicator_opacity?: number;
|
||||||
}) => (
|
}) => (
|
||||||
<div style="position: absolute;top: 0px;bottom: 0px;left: 0px;direction: rtl;font-size: 0px;line-height: 0;pointer-events: none;white-space: nowrap;">
|
<div style="position: absolute;top: 0px;bottom: 0px;left: 0px;direction: rtl;font-size: 0px;line-height: 0;pointer-events: none;white-space: nowrap;">
|
||||||
<div style="overflow: visible;width: 1px;height: 1px;display: inline-block;direction: ltr;vertical-align: text-top;position: relative;top: -9px;left: -9px;">
|
<div style="overflow: visible;width: 1px;height: 1px;display: inline-block;direction: ltr;vertical-align: text-top;position: relative;top: -9px;left: -9px;">
|
||||||
|
@ -410,7 +412,7 @@ export const DragResizableImage = ({
|
||||||
left + 18 + width / 2
|
left + 18 + width / 2
|
||||||
}px;height: ${
|
}px;height: ${
|
||||||
top + 18 + height / 2
|
top + 18 + height / 2
|
||||||
}px; position: relative; opacity: 0.3; background: ${
|
}px; position: relative; opacity: ${indicator_opacity}; background: ${
|
||||||
indicator
|
indicator
|
||||||
? 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAQAAAD8x0bcAAAATklEQVR4AY3OAQYAMQwF0d7/0q2KrzFGZZZVPPLXxlc/RHIjEyIMxBnWBBAFcNODOaSo8X7C3uU/hY3Q5Bwm6vBkCKTiOU3mWkYkI5KQA4BYG/M4zBNLAAAAAElFTkSuQmCC")'
|
? 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAQAAAD8x0bcAAAATklEQVR4AY3OAQYAMQwF0d7/0q2KrzFGZZZVPPLXxlc/RHIjEyIMxBnWBBAFcNODOaSo8X7C3uU/hY3Q5Bwm6vBkCKTiOU3mWkYkI5KQA4BYG/M4zBNLAAAAAElFTkSuQmCC")'
|
||||||
: "none"
|
: "none"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Main, DragResizableImage, render_and_copy } from "./common.tsx";
|
import { Main, DragResizableImage, render_and_copy, n_of } from "./common.tsx";
|
||||||
// this is a really bad and boring idea. pass.
|
|
||||||
// new idea! "make your own image macro" scrollable background of various le classic meme images (imgflip)
|
// new idea! "make your own image macro" scrollable background of various le classic meme images (imgflip)
|
||||||
// + images (yes, images; nobody has impact installed)
|
// + images (yes, images; nobody has impact installed)
|
||||||
// nah. let's just do white + text-shadow
|
// nah. let's just do white + text-shadow
|
||||||
|
@ -98,25 +98,82 @@ const Word = ({
|
||||||
// ughhhh am i going to have to pull out that crappy library
|
// ughhhh am i going to have to pull out that crappy library
|
||||||
// AND download an impact font
|
// AND download an impact font
|
||||||
// (yes)
|
// (yes)
|
||||||
const ScatteredWords = ({ children }: { children: string[] }) => (
|
// tl;dr i can still use this scattering
|
||||||
<>
|
// imagescript can't do the shadow we need (thank goodness)
|
||||||
{...children.map(w => (
|
// maybe imagemagick + photopea then
|
||||||
<Word
|
// i got it (KISS): photopea -> split on command line -> reference by url
|
||||||
top={`${(Math.random() * 100).toFixed(2)}%`}
|
// that should be workable
|
||||||
left={`${(Math.random() * 100).toFixed(2)}%`}
|
|
||||||
>
|
const words = {
|
||||||
{w}
|
THE: 6,
|
||||||
</Word>
|
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 words = `
|
const ScatteredWords = ({ children }: { children: Record<string, number> }) => (
|
||||||
the the the the the the the
|
<>
|
||||||
`
|
{...Object.entries(children).flatMap(([text, count]) =>
|
||||||
.split(/\s+/)
|
// feels pretty snazzy ngl
|
||||||
.filter(Boolean)
|
n_of(Math.ceil(count), () => (
|
||||||
.map(w => w.toUpperCase());
|
<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())
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
render_and_copy(
|
render_and_copy(
|
||||||
<>
|
<>
|
||||||
|
@ -124,20 +181,7 @@ render_and_copy(
|
||||||
style={{ width: "100%", aspectRatio: "1" }}
|
style={{ width: "100%", aspectRatio: "1" }}
|
||||||
aria-described-by="user-content-meme-description"
|
aria-described-by="user-content-meme-description"
|
||||||
>
|
>
|
||||||
<DragResizableImage
|
<ScatteredWords>{words}</ScatteredWords>
|
||||||
url={urls[1]}
|
|
||||||
top={10}
|
|
||||||
left={10}
|
|
||||||
width={10}
|
|
||||||
height={10}
|
|
||||||
/>
|
|
||||||
<DragResizableImage
|
|
||||||
url={urls[2]}
|
|
||||||
top={30}
|
|
||||||
left={10}
|
|
||||||
width={10}
|
|
||||||
height={10}
|
|
||||||
/>
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
@ -163,5 +207,22 @@ render_and_copy(
|
||||||
(hopefully) more accessible version, visit imgflip.com. all of the
|
(hopefully) more accessible version, visit imgflip.com. all of the
|
||||||
memes are taken from there anyway
|
memes are taken from there anyway
|
||||||
</p>
|
</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>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
BIN
static/meme-text/!.png
Normal file
After Width: | Height: | Size: 393 B |
BIN
static/meme-text/A.png
Normal file
After Width: | Height: | Size: 719 B |
BIN
static/meme-text/ALIEN.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
static/meme-text/ARE.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
static/meme-text/BOTTOM.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
static/meme-text/CHUCK_NORRIS.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
static/meme-text/COHOST.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
static/meme-text/EGGBUG.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
static/meme-text/FOR.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
static/meme-text/GET.png
Normal file
After Width: | Height: | Size: 975 B |
BIN
static/meme-text/HOMESTUCK.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
static/meme-text/IMPOSTER.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
static/meme-text/IS.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
static/meme-text/ME.png
Normal file
After Width: | Height: | Size: 755 B |
BIN
static/meme-text/MEHBARK.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
static/meme-text/MEME.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
static/meme-text/NO.png
Normal file
After Width: | Height: | Size: 1,012 B |
BIN
static/meme-text/POST.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
static/meme-text/S.png
Normal file
After Width: | Height: | Size: 850 B |
BIN
static/meme-text/SUCK.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
static/meme-text/SUS.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
static/meme-text/TEXT.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
static/meme-text/THE.png
Normal file
After Width: | Height: | Size: 503 B |
BIN
static/meme-text/THIS.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
static/meme-text/TOP.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
static/meme-text/WEBARK.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
static/meme-text/WHEN.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
static/meme-text/YES.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
static/meme-text/YOU.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
static/meme-text/mother.png
Normal file
After Width: | Height: | Size: 37 KiB |