217 lines
8.4 KiB
Markdown
217 lines
8.4 KiB
Markdown
---
|
||
title: rainbow quox
|
||
date: 2024-12-03
|
||
tags: [computer, website, fursona, december adventure]
|
||
summary: q.t. colour scheme generator
|
||
header-includes: |
|
||
<style>
|
||
#relcolor {
|
||
max-width: 20em; margin: 1em auto auto;
|
||
display: grid; grid-template-columns: 1fr 1fr; gap: 3em;
|
||
font-weight: bold;
|
||
--hi: #ea9aa1; --wow: oklch(from var(--hi) l c calc(h + 180));
|
||
}
|
||
#relcolor div {
|
||
text-align: center; font-size: 125%;
|
||
padding: .4em;
|
||
color: black;
|
||
background: var(--bg);
|
||
border: 4px solid oklch(from var(--bg) .25 75% h);
|
||
box-shadow: 0.5em 0.5em 0 color-mix(in srgb, var(--bg) 50%, transparent);
|
||
}
|
||
#hi { --bg: var(--hi); }
|
||
#wow { --bg: var(--wow); }
|
||
|
||
#patterns { display: flex; gap: 1em; }
|
||
#patterns figure { margin: 0; }
|
||
|
||
#result {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
align-items: center;
|
||
}
|
||
|
||
svg { height: 1.25em; vertical-align: -20%; }
|
||
rect { stroke: currentcolor; stroke-width: 0.075; }
|
||
</style>
|
||
...
|
||
|
||
the animal-inclined might know that [q.t.][qt] can change its colour any time it wants. if you click that link you can clearly see i have some tendencies, but it can in theory be anything. so something i have wanted for a while is a page where you can click a button and get a bespoke randomly-generated quox theme of your very own.
|
||
|
||
so for today's [`@december adventure@`][decadv], i did that. (yesterday's was retroactively the AOC stuff.)
|
||
|
||
[decadv]: https://eli.li/december-adventure
|
||
|
||
:::banner
|
||
[go here if you just want to play with the thing][thing]
|
||
:::
|
||
|
||
[thing]: https://yummy.cricket/rainbow-quox
|
||
|
||
you can also skip to [what i _actually_ ended up doing](#actual), if you don't care about the false starts.
|
||
|
||
[qt]: https://gallery.niss.website/by-any/#qt
|
||
|
||
# doing that
|
||
|
||
{.floating .expandable .nobg .shaped}
|
||
|
||
pretty much what i want to do, at least to begin with, is take the original colours of the image and move the hues around at random.
|
||
|
||
if you look at [mdn], you might see this interesting [`hue-rotate()`][hr] thing that might do what i want. let's have a look.
|
||
|
||
[mdn]: https://developer.mozilla.org/en-US/docs/Web/CSS
|
||
[hr]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/hue-rotate
|
||
|
||
> **Note:** `hue-rotate()` is specified as a matrix operation on the RGB color. It does not actually convert the color to the HSL model, which is a non-linear operation. Therefore, it may not preserve the saturation or lightness of the original color, especially for saturated colors.
|
||
|
||
|
||
{.floating .right .nobg .expandable .shaped}
|
||
|
||
well that doesn't sound very encouraging. but maybe it'll be fine.
|
||
|
||
i shoved [all of the colours][jofo] to hue 0° (using krita's `@hue HSL@` blend mode), and used `hue-rotate()` to change it back to the 'main' colour of each region.
|
||
|
||
it won't look exact, but it'll be close. right?
|
||
|
||
[jofo]: https://johnnyforeigner.bandcamp.com/track/all-of-the-colours
|
||
|
||
{.expandable .nobg}
|
||
|
||
well that's no good at all. i guess that warning was serious.
|
||
|
||
# ok what about blend modes
|
||
|
||
all right, fine. what else. as a chronic over-user of `overlay`, i can certainly tell you that css has a few [blending modes][bm]. not as many as krita, which has approximately "too many", but enough for most purposes. one of them is `hue`. how about that.
|
||
|
||
[bm]: https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode
|
||
|
||
this takes a bit more messing, because i need to create a flood fill of one of the colours from that layer, and blend with that. so how about an SVG filter, i guess. or, six SVG filters---one for each layer, since you can't parametrise them. each one looks like this, with a different `flood-color`.
|
||
|
||
```svg
|
||
<filter id="f-outer">
|
||
<feFlood result="hue" flood-color="#57267e" />
|
||
<feBlend in="hue" in2="SourceGraphic" mode="hue" result="res" />
|
||
<feComposite in="res" in2="SourceGraphic" operator="in" />
|
||
</filter>
|
||
```
|
||
|
||
and…
|
||
|
||
{.expandable .nobg}
|
||
|
||
i was expecting at least the same thing, but a different, also wrong, result is pretty cool.
|
||
|
||
# drastic measures {#actual}
|
||
|
||
ok, enough messing around, time to bite the bullet. separate _every_ colour into its own layer, and use those as masks for colour fills.
|
||
|
||
```css
|
||
#spines {
|
||
background: oklch(30.77% 0.1306 var(--hue)); --hue: 298.19;
|
||
mask-image: url(front/spines.png);
|
||
}
|
||
/* etc… */
|
||
```
|
||
|
||
since the hue is separated out into a variable, i can just randomise them all and instantly have _something_ working.
|
||
|
||
{.expandable .hasborder #chaos}
|
||
|
||
|
||
# digression about relative colours
|
||
|
||
[» skip »](#js)
|
||
|
||
another thing i played with was using [`@relative colours@`][relcol] to generate a whole palette from one starting colour. relative colours work like this: if you have an existing colour `--hi`, you can rotate its hue by half a turn (in real `oklch` this time!!!), keeping its luma and chroma the same, by saying this:
|
||
|
||
```css
|
||
:root {
|
||
--hi: #ea9aa1;
|
||
--wow: oklch(from var(--hi) l c calc(h + 180));
|
||
}
|
||
```
|
||
|
||
<div id=relcolor>
|
||
<div id=hi>\--hi</div>
|
||
<div id=wow>\--wow</div>
|
||
</div>
|
||
|
||
[relcol]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_colors/Relative_colors
|
||
|
||
so i tried that. after guessing a bunch of relative colours, i ended up with this:
|
||
|
||
{.expandable .nobg}
|
||
|
||
|
||
# just do it in ~~java~~typescript. fine {#js}
|
||
|
||
that was pretty cool, but i decided i actually want more flexibility. lighter and darker colour schemes. triadic schemes. whatever.
|
||
|
||
maybe that would be possible in pure css with increasingly illegible relative colours. but the randomise button is going to need javascript anyway, so i might as well just fill in the colours directly. but `oklch` is still useful for generating consistent palettes.
|
||
|
||
the constraints for a "good" q.t. are something like:
|
||
|
||
1. the spines should be a similar colour to its main body.
|
||
2. the same applies to the four fin colours; the belly colours; the sock colours; and the mask and claw colours.
|
||
3. the belly should be very different from the rest of the body.
|
||
4. the eyes should be a similar colour to the body, the fins, or the belly.
|
||
5. the vitiligo patches should match the colour that they are on.
|
||
6. the sock stripes should be pale and not too saturated.
|
||
|
||
a good place to start is the same place everyone does: with complementary and triadic colours.
|
||
|
||
:::{#patterns}
|
||
{.expandable .nobg}
|
||
|
||
{.expandable .nobg}
|
||
|
||
{.expandable .nobg}
|
||
:::
|
||
|
||
using this as a starting point, i pick some evenly-spaced colours for each bit. the final palettes come out like this!
|
||
|
||
:::{#result}
|
||
- fins
|
||
<svg viewBox='-0.1 -0.1 8.7 1.2'>
|
||
<rect fill=#770084 width=2 height=1 />
|
||
<rect fill=#9d0058 width=2 height=1 x=2 />
|
||
<rect fill=#a11916 width=2 height=1 x=4 />
|
||
<rect fill=#eead91 width=2 height=1 x=6.5 />
|
||
</svg>
|
||
- body
|
||
<svg viewBox='-0.1 -0.1 6.7 1.2'>
|
||
<rect fill=#00709b width=2 height=1 />
|
||
<rect fill=#008fca width=2 height=1 x=2 />
|
||
<rect fill=#7dd1f1 width=2 height=1 x=4.5 />
|
||
</svg>
|
||
- belly
|
||
<svg viewBox='-0.1 -0.1 8.7 1.2'>
|
||
<rect fill=#dc8d7b width=2 height=1 />
|
||
<rect fill=#efa4b0 width=2 height=1 x=2 />
|
||
<rect fill=#f9aba1 width=2 height=1 x=4.5 />
|
||
<rect fill=#e3adbc width=2 height=1 x=6.5 />
|
||
</svg>
|
||
- mask/claws/socks
|
||
<svg viewBox='-0.1 -0.1 9.2 1.2'>
|
||
<rect fill=#ebc1c8 width=2 height=1 />
|
||
<rect fill=#b4aaae width=2 height=1 x=2.5 />
|
||
<rect fill=#ffc1a2 width=2 height=1 x=5 />
|
||
<rect fill=#c46c49 width=2 height=1 x=7 />
|
||
</svg>
|
||
|
||
{ .right .expandable .nobg}
|
||
:::
|
||
|
||
# ok what now
|
||
|
||
it's not finished. some things i plan to add at, uh, some point, include:
|
||
|
||
- put [chaos mode](#chaos) back in.
|
||
- permalinks for colour schemes. to do this i need to write another random number generator, since `Math.random` can't be manually seeded. and by "write" i mean "look up online".
|
||
- colour schemes with a light body and dark belly, rather than the other way around.
|
||
- render onto a `<canvas>`, or something. whatever's needed to be able to save the images without having to take a screenshot.
|
||
|
||
:::banner
|
||
[here's the link again to save you scrolling back up][thing]
|
||
:::
|