From d0099fbf19b7681f313c95674e4758aa5970fd60 Mon Sep 17 00:00:00 2001 From: Rhiannon Morris Date: Sat, 7 Dec 2024 21:28:49 +0100 Subject: [PATCH] rainbow quox canvas stuff --- Makefile | 2 +- rainbow-quox/back/belly1.png | 3 - rainbow-quox/back/belly1.webp | 3 + rainbow-quox/back/belly2.png | 3 - rainbow-quox/back/belly2.webp | 3 + rainbow-quox/back/claws.png | 3 - rainbow-quox/back/claws.webp | 3 + rainbow-quox/back/cuffs.png | 3 - rainbow-quox/back/cuffs.webp | 3 + rainbow-quox/back/eyes.png | 3 - rainbow-quox/back/eyes.webp | 3 + rainbow-quox/back/fins1.png | 3 - rainbow-quox/back/fins1.webp | 3 + rainbow-quox/back/fins2.png | 3 - rainbow-quox/back/fins2.webp | 3 + rainbow-quox/back/fins3.png | 3 - rainbow-quox/back/fins3.webp | 3 + rainbow-quox/back/lines.png | 3 - rainbow-quox/back/lines.webp | 3 + rainbow-quox/back/masks.png | 3 - rainbow-quox/back/masks.webp | 3 + rainbow-quox/back/outer.png | 3 - rainbow-quox/back/outer.webp | 3 + rainbow-quox/back/pos.json | 21 ++ rainbow-quox/back/spines.png | 3 - rainbow-quox/back/spines.webp | 3 + rainbow-quox/back/static.png | 3 - rainbow-quox/back/static.webp | 3 + rainbow-quox/back/stripes.png | 3 - rainbow-quox/back/stripes.webp | 3 + rainbow-quox/back/vitiligo1.png | 3 - rainbow-quox/back/vitiligo1.webp | 3 + rainbow-quox/back/vitiligo2.png | 3 - rainbow-quox/back/vitiligo2.webp | 3 + rainbow-quox/back/vitiligo3.png | 3 - rainbow-quox/back/vitiligo3.webp | 3 + rainbow-quox/back/vitiligo4.png | 3 - rainbow-quox/back/vitiligo4.webp | 3 + rainbow-quox/canvas.ts | 325 +++++++++++++++--------------- rainbow-quox/color.ts | 308 ++++++++++++++++------------ rainbow-quox/front/belly1.png | 3 - rainbow-quox/front/belly1.webp | 3 + rainbow-quox/front/belly2.png | 3 - rainbow-quox/front/belly2.webp | 3 + rainbow-quox/front/claws.png | 3 - rainbow-quox/front/claws.webp | 3 + rainbow-quox/front/cuffs.png | 3 - rainbow-quox/front/cuffs.webp | 3 + rainbow-quox/front/eyes.png | 3 - rainbow-quox/front/eyes.webp | 3 + rainbow-quox/front/fins1.png | 3 - rainbow-quox/front/fins1.webp | 3 + rainbow-quox/front/fins2.png | 3 - rainbow-quox/front/fins2.webp | 3 + rainbow-quox/front/fins3.png | 3 - rainbow-quox/front/fins3.webp | 3 + rainbow-quox/front/lines.png | 3 - rainbow-quox/front/lines.webp | 3 + rainbow-quox/front/masks.png | 3 - rainbow-quox/front/masks.webp | 3 + rainbow-quox/front/outer.png | 3 - rainbow-quox/front/outer.webp | 3 + rainbow-quox/front/pos.json | 21 ++ rainbow-quox/front/spines.png | 3 - rainbow-quox/front/spines.webp | 3 + rainbow-quox/front/static.png | 3 - rainbow-quox/front/static.webp | 3 + rainbow-quox/front/stripes.png | 3 - rainbow-quox/front/stripes.webp | 3 + rainbow-quox/front/vitiligo1.png | 3 - rainbow-quox/front/vitiligo1.webp | 3 + rainbow-quox/front/vitiligo2.png | 3 - rainbow-quox/front/vitiligo2.webp | 3 + rainbow-quox/front/vitiligo3.png | 3 - rainbow-quox/front/vitiligo3.webp | 3 + rainbow-quox/front/vitiligo4.png | 3 - rainbow-quox/front/vitiligo4.webp | 3 + rainbow-quox/kra/back.kra | 4 +- rainbow-quox/kra/front.kra | 4 +- rainbow-quox/style.css | 11 +- 80 files changed, 497 insertions(+), 415 deletions(-) delete mode 100644 rainbow-quox/back/belly1.png create mode 100644 rainbow-quox/back/belly1.webp delete mode 100644 rainbow-quox/back/belly2.png create mode 100644 rainbow-quox/back/belly2.webp delete mode 100644 rainbow-quox/back/claws.png create mode 100644 rainbow-quox/back/claws.webp delete mode 100644 rainbow-quox/back/cuffs.png create mode 100644 rainbow-quox/back/cuffs.webp delete mode 100644 rainbow-quox/back/eyes.png create mode 100644 rainbow-quox/back/eyes.webp delete mode 100644 rainbow-quox/back/fins1.png create mode 100644 rainbow-quox/back/fins1.webp delete mode 100644 rainbow-quox/back/fins2.png create mode 100644 rainbow-quox/back/fins2.webp delete mode 100644 rainbow-quox/back/fins3.png create mode 100644 rainbow-quox/back/fins3.webp delete mode 100644 rainbow-quox/back/lines.png create mode 100644 rainbow-quox/back/lines.webp delete mode 100644 rainbow-quox/back/masks.png create mode 100644 rainbow-quox/back/masks.webp delete mode 100644 rainbow-quox/back/outer.png create mode 100644 rainbow-quox/back/outer.webp create mode 100644 rainbow-quox/back/pos.json delete mode 100644 rainbow-quox/back/spines.png create mode 100644 rainbow-quox/back/spines.webp delete mode 100644 rainbow-quox/back/static.png create mode 100644 rainbow-quox/back/static.webp delete mode 100644 rainbow-quox/back/stripes.png create mode 100644 rainbow-quox/back/stripes.webp delete mode 100644 rainbow-quox/back/vitiligo1.png create mode 100644 rainbow-quox/back/vitiligo1.webp delete mode 100644 rainbow-quox/back/vitiligo2.png create mode 100644 rainbow-quox/back/vitiligo2.webp delete mode 100644 rainbow-quox/back/vitiligo3.png create mode 100644 rainbow-quox/back/vitiligo3.webp delete mode 100644 rainbow-quox/back/vitiligo4.png create mode 100644 rainbow-quox/back/vitiligo4.webp delete mode 100644 rainbow-quox/front/belly1.png create mode 100644 rainbow-quox/front/belly1.webp delete mode 100644 rainbow-quox/front/belly2.png create mode 100644 rainbow-quox/front/belly2.webp delete mode 100644 rainbow-quox/front/claws.png create mode 100644 rainbow-quox/front/claws.webp delete mode 100644 rainbow-quox/front/cuffs.png create mode 100644 rainbow-quox/front/cuffs.webp delete mode 100644 rainbow-quox/front/eyes.png create mode 100644 rainbow-quox/front/eyes.webp delete mode 100644 rainbow-quox/front/fins1.png create mode 100644 rainbow-quox/front/fins1.webp delete mode 100644 rainbow-quox/front/fins2.png create mode 100644 rainbow-quox/front/fins2.webp delete mode 100644 rainbow-quox/front/fins3.png create mode 100644 rainbow-quox/front/fins3.webp delete mode 100644 rainbow-quox/front/lines.png create mode 100644 rainbow-quox/front/lines.webp delete mode 100644 rainbow-quox/front/masks.png create mode 100644 rainbow-quox/front/masks.webp delete mode 100644 rainbow-quox/front/outer.png create mode 100644 rainbow-quox/front/outer.webp create mode 100644 rainbow-quox/front/pos.json delete mode 100644 rainbow-quox/front/spines.png create mode 100644 rainbow-quox/front/spines.webp delete mode 100644 rainbow-quox/front/static.png create mode 100644 rainbow-quox/front/static.webp delete mode 100644 rainbow-quox/front/stripes.png create mode 100644 rainbow-quox/front/stripes.webp delete mode 100644 rainbow-quox/front/vitiligo1.png create mode 100644 rainbow-quox/front/vitiligo1.webp delete mode 100644 rainbow-quox/front/vitiligo2.png create mode 100644 rainbow-quox/front/vitiligo2.webp delete mode 100644 rainbow-quox/front/vitiligo3.png create mode 100644 rainbow-quox/front/vitiligo3.webp delete mode 100644 rainbow-quox/front/vitiligo4.png create mode 100644 rainbow-quox/front/vitiligo4.webp diff --git a/Makefile b/Makefile index 76ee9e2..112913d 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ MEDIA = \ $(wildcard media/*.png) $(wildcard media/*.gif) $(wildcard media/*.webp) \ $(wildcard media/flags/*) $(wildcard media/buttons/*) \ $(wildcard media/icons/*) $(wildcard media/bg/*) 8831.png 8831-quox.png \ - $(wildcard rainbow-quox/front/*.png) $(wildcard rainbow-quox/back/*.png) + $(wildcard rainbow-quox/front/*) $(wildcard rainbow-quox/back/*) SCRIPTS = $(patsubst %.ts,%.js,$(wildcard script/*.ts rainbow-quox/*.ts)) MISC = $(shell find .well-known -type f) ALL = $(CSS) $(PAGES) $(MEDIA) $(SCRIPTS) $(MISC) diff --git a/rainbow-quox/back/belly1.png b/rainbow-quox/back/belly1.png deleted file mode 100644 index 8baa6ee..0000000 --- a/rainbow-quox/back/belly1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:936b3d8ff41e8b56747c9e8fbeb461a8daa9837e8fcc17aadbbfa902dc0c7de5 -size 31823 diff --git a/rainbow-quox/back/belly1.webp b/rainbow-quox/back/belly1.webp new file mode 100644 index 0000000..b180728 --- /dev/null +++ b/rainbow-quox/back/belly1.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:17435ce4ea276f54be6e355a86a9cdafcaa0f740e79bf7cd23fe2a054bf2942f +size 10186 diff --git a/rainbow-quox/back/belly2.png b/rainbow-quox/back/belly2.png deleted file mode 100644 index c0cc1df..0000000 --- a/rainbow-quox/back/belly2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:95546e967c48402d64da50c2eb5e4cbee109e2d132f11e6e73f18be8efd609ae -size 26262 diff --git a/rainbow-quox/back/belly2.webp b/rainbow-quox/back/belly2.webp new file mode 100644 index 0000000..963ee27 --- /dev/null +++ b/rainbow-quox/back/belly2.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e4583e2e8da22d32dd9ef8504cb3f1a9b98506c4ec93072f1405857eb28080c +size 11180 diff --git a/rainbow-quox/back/claws.png b/rainbow-quox/back/claws.png deleted file mode 100644 index 8f0480c..0000000 --- a/rainbow-quox/back/claws.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:37767fc980789fffd668903c8f90648076fe1860471455094619d2a197adbe8b -size 15219 diff --git a/rainbow-quox/back/claws.webp b/rainbow-quox/back/claws.webp new file mode 100644 index 0000000..68290cc --- /dev/null +++ b/rainbow-quox/back/claws.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3bf7aae31eb9508d901047727e485f9cb0ec570b02a7503d7fd55ec35ee2144d +size 5866 diff --git a/rainbow-quox/back/cuffs.png b/rainbow-quox/back/cuffs.png deleted file mode 100644 index c2c2e41..0000000 --- a/rainbow-quox/back/cuffs.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f00fe3d6df5686c7087effd62a18810d2cdb9e948a5679f3915414e11224954a -size 18248 diff --git a/rainbow-quox/back/cuffs.webp b/rainbow-quox/back/cuffs.webp new file mode 100644 index 0000000..17b507f --- /dev/null +++ b/rainbow-quox/back/cuffs.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea07cae1405ff4d18c18b75190dee86667e898a2d43059402b8fec5cd4162453 +size 7216 diff --git a/rainbow-quox/back/eyes.png b/rainbow-quox/back/eyes.png deleted file mode 100644 index f36026a..0000000 --- a/rainbow-quox/back/eyes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:270e569cd19f8c4aa5ab6cffd613eb50a68b66d8ab83a895a5094dce339ad724 -size 2494 diff --git a/rainbow-quox/back/eyes.webp b/rainbow-quox/back/eyes.webp new file mode 100644 index 0000000..fa1916d --- /dev/null +++ b/rainbow-quox/back/eyes.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eebdbf997f1fe6bbcb95b07904631197a4a8f9da4901dc52f7b3a4281dd966f2 +size 1834 diff --git a/rainbow-quox/back/fins1.png b/rainbow-quox/back/fins1.png deleted file mode 100644 index 5012332..0000000 --- a/rainbow-quox/back/fins1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5927463cd24394137adb4c21eeffda315e4b85bbd427edfee625dc28db74d1b6 -size 19271 diff --git a/rainbow-quox/back/fins1.webp b/rainbow-quox/back/fins1.webp new file mode 100644 index 0000000..051760d --- /dev/null +++ b/rainbow-quox/back/fins1.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c43e64361cf12fd1368d47a5b2e60d4ab75b471bbedc0bd2e82c01838d09a1fa +size 8934 diff --git a/rainbow-quox/back/fins2.png b/rainbow-quox/back/fins2.png deleted file mode 100644 index 5dc5ed9..0000000 --- a/rainbow-quox/back/fins2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:04da31fc3479fa6aa416bf3d26692241cdc3589a487a308304e120604233620d -size 22619 diff --git a/rainbow-quox/back/fins2.webp b/rainbow-quox/back/fins2.webp new file mode 100644 index 0000000..edfaa31 --- /dev/null +++ b/rainbow-quox/back/fins2.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a3b502e3edc6422fc80ace73b2c10f1a863005ef85f7120de32c264952fbb9b +size 9604 diff --git a/rainbow-quox/back/fins3.png b/rainbow-quox/back/fins3.png deleted file mode 100644 index dfb8a92..0000000 --- a/rainbow-quox/back/fins3.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4e32d31df3b0eaee39b976ee06bab91b7d345a43d247b9539c4780bd15153c88 -size 7710 diff --git a/rainbow-quox/back/fins3.webp b/rainbow-quox/back/fins3.webp new file mode 100644 index 0000000..50ec1c2 --- /dev/null +++ b/rainbow-quox/back/fins3.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2378beb39791d7e76ecdc20161d5f399c0e26f8e803e4ce0b1d86bb89f330dac +size 3336 diff --git a/rainbow-quox/back/lines.png b/rainbow-quox/back/lines.png deleted file mode 100644 index 11d32c7..0000000 --- a/rainbow-quox/back/lines.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dccafcdf3bedcf53a3b4d02296b0a32a8d4129ccc8f900ee03ec48a69b412100 -size 175067 diff --git a/rainbow-quox/back/lines.webp b/rainbow-quox/back/lines.webp new file mode 100644 index 0000000..94e6417 --- /dev/null +++ b/rainbow-quox/back/lines.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9cb5de6589abac930b8c7d524a60ce0f90f2a544455aacc83faa1b75d491c34d +size 75832 diff --git a/rainbow-quox/back/masks.png b/rainbow-quox/back/masks.png deleted file mode 100644 index a6c2634..0000000 --- a/rainbow-quox/back/masks.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:65ef56f98c07512cb61a49dddb878d05745395e0ef3b70a5e2059cadb11dfbcd -size 11064 diff --git a/rainbow-quox/back/masks.webp b/rainbow-quox/back/masks.webp new file mode 100644 index 0000000..43f85cd --- /dev/null +++ b/rainbow-quox/back/masks.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e38d13e93dee8edf287443e107321cdbcd460535ed35708ea770cd9f8b82b7a +size 5054 diff --git a/rainbow-quox/back/outer.png b/rainbow-quox/back/outer.png deleted file mode 100644 index 32050e7..0000000 --- a/rainbow-quox/back/outer.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5f14f71598703bb5cbb8c681c130e1530035c8d880c37c785a031a020efd6f25 -size 53674 diff --git a/rainbow-quox/back/outer.webp b/rainbow-quox/back/outer.webp new file mode 100644 index 0000000..1f494df --- /dev/null +++ b/rainbow-quox/back/outer.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4cebc512183191a771b4897727666df3a3ecf74fa473fe250df969870457ca92 +size 16254 diff --git a/rainbow-quox/back/pos.json b/rainbow-quox/back/pos.json new file mode 100644 index 0000000..f93e41b --- /dev/null +++ b/rainbow-quox/back/pos.json @@ -0,0 +1,21 @@ +{ + "belly1": [39, 67], + "belly2": [92, 95], + "claws": [191, 334], + "cuffs": [221, 215], + "eyes": [685, 42], + "eyeshine": [685, 42], + "fins1": [227, 60], + "fins2": [226, 61], + "fins3": [229, 195], + "lines": [0, 0], + "masks": [643, 1], + "outer": [2, 22], + "spines": [337, 50], + "static": [219, 41], + "stripes": [219, 221], + "vitiligo1": [4, 22], + "vitiligo2": [46, 48], + "vitiligo3": [101, 134], + "vitiligo4": [221, 56] +} diff --git a/rainbow-quox/back/spines.png b/rainbow-quox/back/spines.png deleted file mode 100644 index 52d0ca6..0000000 --- a/rainbow-quox/back/spines.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d74050957003e3899004c8feb2e42238711c8f0a36b7d02d71d5da8ce0d31dd4 -size 14773 diff --git a/rainbow-quox/back/spines.webp b/rainbow-quox/back/spines.webp new file mode 100644 index 0000000..f1fc5b6 --- /dev/null +++ b/rainbow-quox/back/spines.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e2928c46e0a82b93f6f4404116ade0f62cc1252f1f8a2c787d348ca265692f2 +size 7770 diff --git a/rainbow-quox/back/static.png b/rainbow-quox/back/static.png deleted file mode 100644 index fc4d743..0000000 --- a/rainbow-quox/back/static.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fcd0a1acdee002be0d27a9f63324dd67726d3d1e1b928984eee8a5218201e4de -size 30714 diff --git a/rainbow-quox/back/static.webp b/rainbow-quox/back/static.webp new file mode 100644 index 0000000..b871a39 --- /dev/null +++ b/rainbow-quox/back/static.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3574730db19b5c7543c486263b1c6ff4ffde294ea6486fc3a32981300ba9741b +size 14654 diff --git a/rainbow-quox/back/stripes.png b/rainbow-quox/back/stripes.png deleted file mode 100644 index e69e71c..0000000 --- a/rainbow-quox/back/stripes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0854a36214a060929bcce3da6fa5c72d44421ea60f85ffc39ba0e99f02eea466 -size 34634 diff --git a/rainbow-quox/back/stripes.webp b/rainbow-quox/back/stripes.webp new file mode 100644 index 0000000..a9158eb --- /dev/null +++ b/rainbow-quox/back/stripes.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff825e8616b2385276f2bd0091b12372770f764d54de2d3f8ea5efd4afe887c2 +size 15888 diff --git a/rainbow-quox/back/vitiligo1.png b/rainbow-quox/back/vitiligo1.png deleted file mode 100644 index 6b90b62..0000000 --- a/rainbow-quox/back/vitiligo1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:16080417ad3230a645c5bff273c3370f0db00cde84424fc13e90e27354c5a0f9 -size 33461 diff --git a/rainbow-quox/back/vitiligo1.webp b/rainbow-quox/back/vitiligo1.webp new file mode 100644 index 0000000..32bfed2 --- /dev/null +++ b/rainbow-quox/back/vitiligo1.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c037de4c156b9aebc2b221c7167c5ea7ffae49c1480a0f678275c08997dddc5 +size 14106 diff --git a/rainbow-quox/back/vitiligo2.png b/rainbow-quox/back/vitiligo2.png deleted file mode 100644 index 6da0281..0000000 --- a/rainbow-quox/back/vitiligo2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3e0c30c5058ebe7febf9a0a1811801ee7f8bf2cab86343669cec22061d82ca08 -size 7283 diff --git a/rainbow-quox/back/vitiligo2.webp b/rainbow-quox/back/vitiligo2.webp new file mode 100644 index 0000000..d17c37b --- /dev/null +++ b/rainbow-quox/back/vitiligo2.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1db28390d6407495f8c0a0125db81f8d5e15d363463c04dc77748808fbd97eb7 +size 2632 diff --git a/rainbow-quox/back/vitiligo3.png b/rainbow-quox/back/vitiligo3.png deleted file mode 100644 index c67913c..0000000 --- a/rainbow-quox/back/vitiligo3.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a688d2fe7f603d2360ff027b20091a60cb710873204bdf0adfabec73a1f3be65 -size 7040 diff --git a/rainbow-quox/back/vitiligo3.webp b/rainbow-quox/back/vitiligo3.webp new file mode 100644 index 0000000..0899891 --- /dev/null +++ b/rainbow-quox/back/vitiligo3.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:195c7aaf80305f17cbee871b59bf3f797628aafb09701567b22549ae68626f27 +size 2578 diff --git a/rainbow-quox/back/vitiligo4.png b/rainbow-quox/back/vitiligo4.png deleted file mode 100644 index 3d34316..0000000 --- a/rainbow-quox/back/vitiligo4.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1cf7bd357602ac2ffee7d2b364562ef5b29065e6090023c71fd6631762126771 -size 13109 diff --git a/rainbow-quox/back/vitiligo4.webp b/rainbow-quox/back/vitiligo4.webp new file mode 100644 index 0000000..5ccc13d --- /dev/null +++ b/rainbow-quox/back/vitiligo4.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dabdb0e89303ef963a74f864301a9e501377fe2521e7856fcdc569a7ca53dc79 +size 5824 diff --git a/rainbow-quox/canvas.ts b/rainbow-quox/canvas.ts index 8f989b6..86d90d3 100644 --- a/rainbow-quox/canvas.ts +++ b/rainbow-quox/canvas.ts @@ -12,83 +12,36 @@ export const allLayers: Layer[] = 'belly1', 'belly2', 'masks', 'claws', 'vitiligo1', 'vitiligo2', 'vitiligo3', 'vitiligo4', 'eyes', 'eyeshine', 'lines']; -export type Image = ImageData; -export type Images = Record; - -export type ComposedImages = Images & {comp?: ImageData}; - -export type Side = 'front' | 'back'; - -export function flip(s: Side): Side { - return s == 'front' ? 'back' : 'front'; +export function makeLayerInfo(f: (l: Layer) => A): Record { + return Object.fromEntries(allLayers.map(l => [l, f(l)])) as Record; } +export type Position = [x: number, y: number]; +export type Positions = Record; -let buffer = new OffscreenCanvas(WIDTH, HEIGHT); -let bufferCtx = buffer.getContext('2d')!; +export async function loadPos(side: SideName): Promise { + let req = new Request(`./${side}/pos.json`); + return fetch(req).then(resp => resp.json()); +} -type Positions = Record; +export type LayerInfo1 = {data: ImageData, pos: Position}; -const FRONT_POS: Positions = { - belly1: [187, 105], - belly2: [186, 91], - claws: [3, 168], - cuffs: [42, 160], - eyes: [223, 52], - eyeshine: [223, 52], - fins1: [381, 31], - fins2: [387, 35], - fins3: [495, 140], - lines: [1, 0], - masks: [173, 3], - outer: [28, 43], - spines: [372, 23], - static: [50, 52], - stripes: [50, 168], - vitiligo1: [34, 23], - vitiligo2: [198, 92], - vitiligo3: [214, 312], - vitiligo4: [647, 71], -}; - -const BACK_POS: Positions = { - belly1: [39, 67], - belly2: [92, 95], - claws: [191, 334], - cuffs: [221, 215], - eyes: [685, 42], - eyeshine: [685, 42], - fins1: [227, 60], - fins2: [226, 61], - fins3: [229, 195], - lines: [0, 0], - masks: [643, 1], - outer: [2, 22], - spines: [337, 50], - static: [219, 41], - stripes: [219, 221], - vitiligo1: [4, 22], - vitiligo2: [46, 48], - vitiligo3: [101, 134], - vitiligo4: [221, 56], +export type LayerInfo = { + layers: Record, + comp?: ImageData, }; type Rgb = [number, number, number]; type Rgbs = Record; +let rgbBuf = new OffscreenCanvas(1, 1).getContext('2d')!; + function toRgb(col: Color.Oklch): Rgb { // :) - const prev = bufferCtx.getImageData(0, 0, 1, 1); - - bufferCtx.save(); - bufferCtx.fillStyle = Color.oklch(col); - bufferCtx.fillRect(0, 0, 1, 1); - bufferCtx.restore(); - - const rgb = bufferCtx.getImageData(0, 0, 1, 1).data; - bufferCtx.putImageData(prev, 0, 0); - + rgbBuf.fillStyle = col.css(); + rgbBuf.fillRect(0, 0, 1, 1); + const rgb = rgbBuf.getImageData(0, 0, 1, 1).data; return [rgb[0]!, rgb[1]!, rgb[2]!]; } @@ -97,98 +50,92 @@ function toRgbs(col: Color.Colors): Rgbs { } -function setImageDataRgb([r, g, b]: Rgb, img: Image): void { - let data = img.data; +function setImageDataRgb({ data }: ImageData, [r, g, b]: Rgb, a: number = -1) { for (let i = 0; i < data.length; i += 4) { data[i] = r; data[i+1] = g; data[i+2] = b; + if (a >= 0) data[i+3]! *= a; } } -async function wait(img: HTMLImageElement): Promise { - if (img.complete) { - return new Promise((r, _) => r(img)); - } else { - return new Promise((r, _) => img.addEventListener('load', () => r(img))); - } +async function loadImage(url: string): Promise { + const img0 = new Image; img0.src = url; + const img: ImageBitmapSource = img0.complete ? img0 : + await new Promise(r => img0.addEventListener('load', () => r(img0))); + return createImageBitmap(img); } -async function load(side: Side, layer: Layer): Promise { +async function load(buf: OffscreenCanvasRenderingContext2D, + side: SideName, layer: Layer): Promise { if (layer == 'eyeshine') layer = 'eyes'; - let img = new Image; img.src = `./${side}/${layer}.png`; - let bmp = await createImageBitmap(await wait(img)); - bufferCtx.clearRect(0, 0, WIDTH, HEIGHT); // ? - bufferCtx.drawImage(bmp, 0, 0); - return bufferCtx.getImageData(0, 0, WIDTH, HEIGHT); + let bmp = await loadImage(`./${side}/${layer}.webp`); + return navigator.locks.request('buf', async () => { + buf.clearRect(0, 0, WIDTH, HEIGHT); // ? + buf.drawImage(bmp, 0, 0); + return buf.getImageData(0, 0, WIDTH, HEIGHT) + }); } -async function loadSide(side: Side): Promise { - const res: Partial = { }; - for (const l of allLayers) { res[l] = await load(side, l); } - return res as ComposedImages; +async function loadSide(buf: OffscreenCanvasRenderingContext2D, + side: SideName): Promise { + const layers: Partial> = { }; + const pos = await loadPos(side); + const images = Object.fromEntries( + await Promise.all( + allLayers.map(l => load(buf, side, l).then(res => [l, res]))) + ) as Record; + console.log(images); + for (const l of allLayers) { + layers[l] = { data: images[l], pos: pos[l] }; + } + return { layers: layers as Record }; } -function setColors(cols: Rgbs, layers: ComposedImages): void { - bufferCtx.save(); - +function setColors(cols: Rgbs, info: LayerInfo): void { for (const l of allLayers) { if (l == 'static' || l == 'eyeshine') continue; - setImageDataRgb(cols[l], layers[l]); + setImageDataRgb(info.layers[l].data, cols[l]); } - - delete layers.comp; - - bufferCtx.restore(); + delete info.comp; } -async function compose(layers: Images, pos: Positions): Promise { - bufferCtx.save(); - bufferCtx.clearRect(0, 0, WIDTH, HEIGHT); +async function compose(buf: OffscreenCanvasRenderingContext2D, + { layers }: LayerInfo): Promise { + return navigator.locks.request('buf', async () => { + buf.save(); + buf.clearRect(0, 0, WIDTH, HEIGHT); - for (const l of allLayers) { - const [x, y] = pos[l]; - bufferCtx.globalCompositeOperation = - l == 'eyeshine' ? 'luminosity' : 'source-over'; - bufferCtx.drawImage(await createImageBitmap(layers[l]), x, y); - } + for (const l of allLayers) { + const [x, y] = layers[l].pos; + buf.globalCompositeOperation = + l == 'eyeshine' ? 'luminosity' : 'source-over'; + buf.drawImage(await createImageBitmap(layers[l].data), x, y); + } - let res = bufferCtx.getImageData(0, 0, WIDTH, HEIGHT); - bufferCtx.restore(); - - return res; + buf.restore(); + return buf.getImageData(0, 0, WIDTH, HEIGHT); + }); } async function redraw(ctx: CanvasRenderingContext2D, - layers: ComposedImages, pos: Positions) { - let data = layers.comp ??= await compose(layers, pos); + buf: OffscreenCanvasRenderingContext2D, + info: LayerInfo) { + let data = info.comp ??= await compose(buf, info); ctx.putImageData(data, 0, 0); } -async function loadingMessage(): Promise { - bufferCtx.save(); - bufferCtx.clearRect(0, 0, WIDTH, HEIGHT); - bufferCtx.font = 'bold 100px Muller, sans-serif'; - bufferCtx.textAlign = 'center'; - bufferCtx.fillText('loading layers…', WIDTH/2, HEIGHT/2); - let res = createImageBitmap(buffer); - bufferCtx.restore(); - return await res; +function message(msg: string, ctx: CanvasRenderingContext2D) { + ctx.save(); + ctx.clearRect(0, 0, WIDTH, HEIGHT); + ctx.font = 'bold 100px Muller, sans-serif'; + ctx.textAlign = 'center'; + ctx.fillText(msg, WIDTH/2, HEIGHT/2); + ctx.restore(); } -let pic: HTMLCanvasElement; -let picCtx: CanvasRenderingContext2D; - -let pic2: HTMLCanvasElement; -let pic2Ctx: CanvasRenderingContext2D; - -let fronts: Images; -let backs: Images; - -let side: Side = 'front'; - function startAnim(name: string) { document.documentElement.dataset.running = name; } @@ -201,17 +148,38 @@ function finishAnim() { delete document.documentElement.dataset.running; } -function layers(): Images { return side == 'front' ? fronts : backs; } -function pos(): Positions { return side == 'front' ? FRONT_POS : BACK_POS; } +type SideName = 'front' | 'back'; +class Side { + cur: SideName = 'front'; + fronts: LayerInfo; + backs: LayerInfo; -async function recolorOn(ctx: CanvasRenderingContext2D) { - const cols = Color.colors(); - const rgbs = toRgbs(cols); - setColors(rgbs, fronts); - setColors(rgbs, backs); - await redraw(ctx, layers(), pos()); - return cols.outer.h; + private constructor(fronts: LayerInfo, backs: LayerInfo) { + this.fronts = fronts; this.backs = backs; + } + + static async init(buf: OffscreenCanvasRenderingContext2D) { + return new Side(await loadSide(buf, 'front'), await loadSide(buf, 'back')); + } + + flip() { this.cur = (this.cur == 'front' ? 'back' : 'front'); } + layers() { return this.cur == 'front' ? this.fronts : this.backs; } + + async recolorOn(ctx: CanvasRenderingContext2D, + buf: OffscreenCanvasRenderingContext2D) { + const cols = Color.colors(); + const rgbs = toRgbs(cols); + setColors(rgbs, this.fronts); + setColors(rgbs, this.backs); + await redraw(ctx, buf, this.layers()); + return cols.outer.h; + } + + async ensureComposed(buf: OffscreenCanvasRenderingContext2D) { + this.fronts.comp ??= await compose(buf, this.fronts); + this.backs.comp ??= await compose(buf, this.backs); + } } function setBg(hue: number) { @@ -219,56 +187,77 @@ function setBg(hue: number) { } -async function animateReroll(_e: Event, done: () => void) { - const duration = 400; - const hue = await recolorOn(pic2Ctx); - pic2.style.animation = `${duration}ms ease fade-in`; +async function animateReroll(ctx1: CanvasRenderingContext2D, + ctx2: CanvasRenderingContext2D, + buf: OffscreenCanvasRenderingContext2D, + side: Side, + done: () => void) { + const duration = 200; + const hue = await side.recolorOn(ctx2, buf); + ctx2.canvas.style.animation = `${duration}ms ease fade-in`; setBg(hue); setTimeout(finish, duration); async function finish() { - await redraw(picCtx, layers(), pos()).then(() => { - pic2.style.removeProperty('animation'); - pic2.style.removeProperty('opacity'); + await redraw(ctx1, buf, side.layers()).then(() => { + ctx2.canvas.style.removeProperty('animation'); + ctx2.canvas.style.removeProperty('opacity'); done(); }); } } -function animateSwap(_e: Event, done: () => void) { - const duration = 1000; - pic.style.animation = `${duration}ms ease swap`; - setTimeout(swapImage, duration/2); +async function animateSwap(picCtx: CanvasRenderingContext2D, + pic2Ctx: CanvasRenderingContext2D, + side: Side, + buf: OffscreenCanvasRenderingContext2D, + done: () => void) { + const duration = 400; + + side.flip(); + await Promise.all([ + side.ensureComposed(buf), + redraw(pic2Ctx, buf, side.layers()), + ]); + + picCtx.canvas.style.animation = `${duration}ms ease swap1`; + pic2Ctx.canvas.style.animation = `${duration}ms ease swap2`; + setTimeout(swap, duration/2); setTimeout(finish, duration); - async function swapImage() { - side = flip(side); - await redraw(picCtx, layers(), pos()); + function swap() { + let data = pic2Ctx.getImageData(0, 0, WIDTH, HEIGHT); + picCtx.putImageData(data, 0, 0); } function finish() { - pic.style.removeProperty('animation'); + picCtx.canvas.style.removeProperty('animation'); + pic2Ctx.canvas.style.removeProperty('animation'); done(); } } + document.addEventListener('DOMContentLoaded', async function() { - pic = document.getElementById('pic') as HTMLCanvasElement; - picCtx = pic.getContext('2d')!; + let pic = document.getElementById('pic') as HTMLCanvasElement; + let picCtx = pic.getContext('2d')!; - pic2 = document.getElementById('pic2') as HTMLCanvasElement; - pic2Ctx = pic2.getContext('2d')!; + let pic2 = document.getElementById('pic2') as HTMLCanvasElement; + let pic2Ctx = pic2.getContext('2d')!; - picCtx.drawImage(await loadingMessage(), 0, 0); + let buf = new OffscreenCanvas(WIDTH, HEIGHT).getContext('2d')!; - fronts = await loadSide('front'); - backs = await loadSide('back'); - side = 'front'; + message('loading layers…', picCtx); - let hue = await recolorOn(picCtx); + let side: Side = await Side.init(buf).catch(err => { + message(err, picCtx); + throw err; + }); + + let hue = await side.recolorOn(picCtx, buf); setBg(hue); - await redraw(picCtx, layers(), pos()); + await redraw(picCtx, buf, side.layers()); const reroll = document.getElementById('reroll')!; const swap = document.getElementById('swap')!; @@ -285,19 +274,25 @@ document.addEventListener('DOMContentLoaded', async function() { swap.removeEventListener('click', handleSwap); } - function handleReroll(e: Event) { wrap(reroll, animateReroll, 'reroll', e); } - function handleSwap(e: Event) { wrap(swap, animateSwap, 'swap', e); } + function handleReroll(e: Event) { + wrap(reroll, done => animateReroll(picCtx, pic2Ctx, buf, side, done), + 'reroll', e); + } - type HandlerWithFinish = (e: Event, finish: () => void) => void; + function handleSwap(e: Event) { + wrap(swap, done => animateSwap(picCtx, pic2Ctx, side, buf, done), + 'swap', e); + } - function wrap(elem: Element, f: HandlerWithFinish, - name: string, e: Event) { + type Handler = (finish: () => void) => void; + + function wrap(elem: Element, f: Handler, name: string, e: Event) { if (elem != e.target) return; e.stopPropagation(); if (isRunning()) return; removeListeners(); startAnim(name); - f(e, () => { finishAnim(); addListeners(); }); + f(() => { finishAnim(); addListeners(); }); } }); diff --git a/rainbow-quox/color.ts b/rainbow-quox/color.ts index 337a33f..9de056b 100644 --- a/rainbow-quox/color.ts +++ b/rainbow-quox/color.ts @@ -1,16 +1,131 @@ const rand: () => number = Math.random; // [todo] +function randBetween(x: number, y: number): number { + const lo = min(x, y), hi = max(x, y); + return lo + rand() * (hi - lo); +} + +function oneOf(...xs: A[]): A { + return xs[Math.floor(rand() * xs.length)]!; +} + const max = Math.max; const min = Math.min; -export type Oklch = { l: number, c: number, h: number }; - -export function oklch(col: Oklch, alpha: number = 1): string { - return `oklch(${col.l} ${col.c} ${col.h} / ${alpha})`; -} type LD = 'light' | 'dark'; +namespace Oklch { + export type Channel = 'l' | 'c' | 'h'; + export type Channels = Record; + export type ChannelMap = (x: number) => number; + export type ChannelMaps = Record; +} + +export class Oklch { + static lightFor(baseL: number): number { return randBetween(baseL, MAXL); } + + static darkFor(baseL: number): number { return randBetween(MINL, baseL); } + + static isLight(l: number): boolean { return l >= MINL_LIGHT; } + + static brightFor(l: number, baseC: number): number { + if (Oklch.isLight(l)) { return randBetween(baseC, MAXC_LIGHT); } + else { return randBetween(baseC, MAXC_DARK); } + } + + static dullFor(l: number, baseC: number): number { + if (Oklch.isLight(l)) { return randBetween(baseC, MINC_LIGHT); } + else { return randBetween(baseC, MINC_DARK); } + } + + static analogous1(baseH: number): number { + const size = randBetween(MINH_SEP, 2 * MINH_SEP); + return rand() > 0.5 ? baseH + size : baseH - size; + } + + static analogous(baseH: number, count: number): number[] { + const minWidth = min(count * MINH_SEP, MAXH_WIDTH * 0.8); + const width = randBetween(minWidth, MAXH_WIDTH); + const sep = width / (count - 1); + const start = baseH - (width / 2); + const numbers = Array.from({length: count}, (_u, i) => start + i * sep); + return rand() > 0.5 ? numbers : numbers.reverse(); + } + + static complementary1(baseH: number): number { + return Oklch.analogous1((baseH + 180) % 360); + } + + static complementary(baseH: number, count: number): number[] { + const angle = randBetween(180 - MAXH_COMPL/2, 180 + MAXH_COMPL/2); + return Oklch.analogous(baseH + angle, count); + } + + static triad(baseH: number): [number, number] { + const angle = randBetween(120 - MAXH_TRIAD/2, 120 + MAXH_TRIAD/2); + return [baseH - angle, baseH + angle]; + } + + readonly l: number; readonly c: number; readonly h: number; + + static baseLuma(ld?: LD): number { + if (ld == 'light') { + return randBetween(MINL_LIGHT, MAXL); + } else if (ld == 'dark') { + return randBetween(MINL, MAXL_DARK); + } else { + return randBetween(MINL, MAXL); + } + } + + static baseChroma(l: number): number { + if (l >= MINL_LIGHT) { + return randBetween(MINC_LIGHT, MAXC_LIGHT); + } else { + return randBetween(MINC_DARK, MAXC_DARK); + } + } + + static baseHue(): number { return rand() * 360; } + + constructor(); + constructor(ld: LD); + constructor(cs: Oklch.Channels); + constructor(l: number, c: number, h: number); + constructor(lcsld?: number | Oklch.Channels | LD, + cc?: number, hh?: number) { + if (typeof lcsld == 'string' || lcsld == undefined) { + this.l = Oklch.baseLuma(lcsld as LD | undefined); + this.c = Oklch.baseChroma(this.l); + this.h = Oklch.baseHue(); + } else if (cc == undefined && hh == undefined) { + const {l, c, h} = lcsld as Oklch.Channels; + this.l = l; this.c = c; this.h = h; + } else { + this.l = lcsld as number; this.c = cc!; this.h = hh!; + } + } + + css(alpha: number = 1): string { + return `oklch(${this.l} ${this.c} ${this.h} / ${alpha})`; + } + + with(lch: Partial>): Oklch { + function call(comp: undefined | number | Oklch.ChannelMap, x: number) { + if (comp == undefined) { return x; } + else if (typeof comp == 'function') { return comp(x); } + else { return comp as number; } + } + return new Oklch({ + l: call(lch.l, this.l), + c: call(lch.c, this.c), + h: call(lch.h, this.h), + }); + } +} + + const MAXL = 0.9; const MINL = 0.4; const MINL_LIGHT = 0.7; @@ -34,89 +149,6 @@ const MAXH_COMPL = 40; // size of the wedge a "triadic" color can be in const MAXH_TRIAD = 25; -function randBetween(x: number, y: number): number { - const lo = min(x, y), hi = max(x, y); - return lo + rand() * (hi - lo); -} - -function oneOf(...xs: A[]): A { - return xs[Math.floor(rand() * xs.length)]!; -} - - -function baseLuma(ld?: LD): number { - if (ld == 'light') { - return randBetween(MINL_LIGHT, MAXL); - } else if (ld == 'dark') { - return randBetween(MINL, MAXL_DARK); - } else { - return randBetween(MINL, MAXL); - } -} - -function baseChroma(l: number): number { - if (l >= MINL_LIGHT) { - return randBetween(MINC_LIGHT, MAXC_LIGHT); - } else { - return randBetween(MINC_DARK, MAXC_DARK); - } -} - -function baseHue(): number { return rand() * 360; } - -function baseOklch(ld?: LD): Oklch { - const l = baseLuma(ld); - return { l, c: baseChroma(l), h: baseHue() }; -} - -function lightFor(baseL: number): number { - return randBetween(baseL, MAXL); -} -function darkFor(baseL: number): number { - return randBetween(MINL, baseL); -} - -function isLight(l: number): boolean { return l >= MINL_LIGHT; } - -function brightFor(l: number, baseC: number): number { - if (isLight(l)) { return randBetween(baseC, MAXC_LIGHT); } - else { return randBetween(baseC, MAXC_DARK); } -} - -function dullFor(l: number, baseC: number): number { - if (isLight(l)) { return randBetween(baseC, MINC_LIGHT); } - else { return randBetween(baseC, MINC_DARK); } -} - - -function analogous1(baseH: number): number { - const size = randBetween(MINH_SEP, 2 * MINH_SEP); - return rand() > 0.5 ? baseH + size : baseH - size; -} - -function analogous(baseH: number, count: number): number[] { - const minWidth = min(count * MINH_SEP, MAXH_WIDTH * 0.8); - const width = randBetween(minWidth, MAXH_WIDTH); - const sep = width / (count - 1); - const start = baseH - (width / 2); - const numbers = Array.from({length: count}, (_u, i) => start + i * sep); - return rand() > 0.5 ? numbers : numbers.reverse(); -} - -function complementary1(baseH: number): number { - return analogous1((baseH + 180) % 360); -} - -function complementary(baseH: number, count: number): number[] { - const angle = randBetween(180 - MAXH_COMPL/2, 180 + MAXH_COMPL/2); - return analogous(baseH + angle, count); -} - -function triad(baseH: number): [number, number] { - const angle = randBetween(120 - MAXH_TRIAD/2, 120 + MAXH_TRIAD/2); - return [baseH - angle, baseH + angle]; -} - export type SchemeType = 'triad' | 'fin-belly' | 'fin-body'; export type OuterLayer = 'outer' | 'spines' | 'vitiligo1'; @@ -148,7 +180,7 @@ export function makeColorInfo(f: (l: Layer) => A): Record { export function colors(): Scheme { - const outer = baseOklch('dark'); + const outer = new Oklch('dark'); let outerCols: OuterCols = { outer, spines: mkSpines(outer), vitiligo1: mkVitiligo(outer) }; @@ -159,16 +191,16 @@ export function colors(): Scheme { const whichBody = rand(); if (whichBody > 2/3) { type = 'triad'; - const [f, b] = triad(outer.h); + const [f, b] = Oklch.triad(outer.h); finCols = mkFins(f, outer); bellyCols = mkBelly(b); } else if (whichBody > 1/3) { type = 'fin-belly'; - const [f, b] = complementary(outer.h, 2); + const [f, b] = Oklch.complementary(outer.h, 2); finCols = mkFins(f!, outer); bellyCols = mkBelly(b!); } else { type = 'fin-body'; - finCols = mkFins(analogous1(outer.h), outer); - bellyCols = mkBelly(complementary1(outer.h)); + finCols = mkFins(Oklch.analogous1(outer.h), outer); + bellyCols = mkBelly(Oklch.complementary1(outer.h)); } let miscCols = mkMisc(outerCols, finCols, bellyCols); @@ -178,80 +210,88 @@ export function colors(): Scheme { function mkSpines(outer: Oklch): Oklch { - return { - l: outer.l * 0.8, c: outer.c * 1.1, - h: randBetween(outer.h + 12, outer.h - 12) - }; + return outer.with({ + l: x => x * 0.8, + c: x => x * 1.1, + h: x => randBetween(x + 12, x - 12), + }) } function mkVitiligo(outer: Oklch): Oklch { - return { - l: randBetween(max(outer.l, 0.94), 0.985), // exception to MAXL - c: randBetween(min(outer.c, 0.1), MINC_LIGHT), - h: outer.h - }; + return outer.with({ + l: x => randBetween(max(x, 0.94), 0.985), // exception to MAXL + c: x => randBetween(min(x, 0.1), MINC_LIGHT), + }); } function mkStripes(): Oklch { - return { + return new Oklch({ l: randBetween(0.8, MAXL), c: randBetween(MINC_LIGHT, MAXC_LIGHT), h: rand() * 360 - }; + }); } function mkCuffs(sock: Oklch): Oklch { - return { - l: randBetween(sock.l * 0.85, sock.l * 0.65), - c: randBetween(sock.c, MAXC_LIGHT), - h: randBetween(sock.h + 8, sock.h - 8) - }; + return sock.with({ + l: x => randBetween(x * 0.85, x * 0.65), + c: x => randBetween(x, MAXC_LIGHT), + h: x => randBetween(x + 8, x - 8), + }); } function mkFins(h: number, outer: Oklch): FinCols { - const [fin1Hue, fin2Hue, fin3Hue] = analogous(h, 3); - const [ll, cc] = oneOf([lightFor, dullFor], [darkFor, brightFor]); - const fins1 = { l: ll(outer.l), c: cc(outer.l, outer.c), h: fin1Hue! }; - const fins2 = { l: ll(fins1.l), c: cc(fins1.l, fins1.c), h: fin2Hue! }; - const fins3 = { l: ll(fins2.l), c: cc(fins2.l, fins2.c), h: fin3Hue! }; + const [fin1Hue, fin2Hue, fin3Hue] = Oklch.analogous(h, 3); + const [ll, cc] = oneOf( + [Oklch.lightFor, Oklch.dullFor], [Oklch.darkFor, Oklch.brightFor]); + + const fins1 = new Oklch(ll(outer.l), cc(outer.l, outer.c), fin1Hue!); + const fins2 = new Oklch(ll(fins1.l), cc(fins1.l, fins1.c), fin2Hue!); + const fins3 = new Oklch(ll(fins2.l), cc(fins2.l, fins2.c), fin3Hue!); const vitiligo4 = mkVitiligo(fins1); return { fins1, fins2, fins3, vitiligo4 }; } function mkBelly(h: number): BellyCols { - const [belly1Hue, belly2Hue] = analogous(h, 2); - const belly1 = - { l: randBetween(0.7, MAXL), c: baseChroma(1), h: belly1Hue! }; - const belly2 = - { l: min(MAXL, belly1.l * 1.1), c: belly1.c * 0.9, h: belly2Hue! }; + const [belly1Hue, belly2Hue] = Oklch.analogous(h, 2); + const belly1 = new Oklch({ + l: randBetween(0.7, MAXL), + c: Oklch.baseChroma(1), + h: belly1Hue! + }); + const belly2 = belly1.with({ + l: x => min(MAXL, x * 1.1), + c: x => x * 0.9, + h: belly2Hue!, + }); const vitiligo3 = mkVitiligo(belly1); const vitiligo2 = mkVitiligo(belly2); return { belly1, belly2, vitiligo2, vitiligo3 }; } function mkMisc(o: OuterCols, f: FinCols, b: BellyCols): MiscCols { - const masks = { + const masks = new Oklch({ l: randBetween(0.8, MAXL), c: randBetween(0.01, 0.06), - h: analogous1(oneOf(o.outer, b.belly1, f.fins1).h) - }; + h: Oklch.analogous1(oneOf(o.outer, b.belly1, f.fins1).h) + }); return { masks, - eyes: { - l: baseLuma('light'), + eyes: new Oklch({ + l: Oklch.baseLuma('light'), c: randBetween(0.28, MAXC_LIGHT), - h: oneOf(analogous1, complementary1)(o.outer.h) - }, - claws: { - l: min(MAXL, masks.l + randBetween(0, 0.1)), + h: oneOf(Oklch.analogous1, Oklch.complementary1)(o.outer.h) + }), + claws: masks.with({ + l: x => min(MAXL, x + randBetween(0, 0.1)), c: randBetween(0.01, 0.06), - h: analogous1(masks.h) - }, - lines: { + h: Oklch.analogous1, + }), + lines: new Oklch({ l: randBetween(0.01, 0.06), - c: baseChroma(0), - h: analogous1(o.outer.h) - } + c: Oklch.baseChroma(0), + h: Oklch.analogous1(o.outer.h) + }), }; } diff --git a/rainbow-quox/front/belly1.png b/rainbow-quox/front/belly1.png deleted file mode 100644 index 778fc65..0000000 --- a/rainbow-quox/front/belly1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:018fa612600c9819e2d5256e9a3f11d025cee9ee544e7a6e05f2c08cb0d01c64 -size 32398 diff --git a/rainbow-quox/front/belly1.webp b/rainbow-quox/front/belly1.webp new file mode 100644 index 0000000..c04d004 --- /dev/null +++ b/rainbow-quox/front/belly1.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7a0574268f1913792486b092a12961b6e5b10fdb21a5e48be527dc1b63a785b +size 9078 diff --git a/rainbow-quox/front/belly2.png b/rainbow-quox/front/belly2.png deleted file mode 100644 index e4a8188..0000000 --- a/rainbow-quox/front/belly2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ec027a0197521656c8d4a6a49a31abb4847dbbf9de6e29cdbd9b329bb8c959ce -size 33178 diff --git a/rainbow-quox/front/belly2.webp b/rainbow-quox/front/belly2.webp new file mode 100644 index 0000000..f420bde --- /dev/null +++ b/rainbow-quox/front/belly2.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b36476275d883bfe11a6287310166a9c6cbfcbd534f415c46dda598f7c26a16 +size 14686 diff --git a/rainbow-quox/front/claws.png b/rainbow-quox/front/claws.png deleted file mode 100644 index dbb913d..0000000 --- a/rainbow-quox/front/claws.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5ea380fb19422ab0b375b24839ecb70140cc7bb73035c9b3ffbb62d937b61497 -size 21353 diff --git a/rainbow-quox/front/claws.webp b/rainbow-quox/front/claws.webp new file mode 100644 index 0000000..861ddbd --- /dev/null +++ b/rainbow-quox/front/claws.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e220c631d24393db8328b2a5cadf1aed5102fec789dbfa3aab40b7bbc92794c +size 8714 diff --git a/rainbow-quox/front/cuffs.png b/rainbow-quox/front/cuffs.png deleted file mode 100644 index 1871a7b..0000000 --- a/rainbow-quox/front/cuffs.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7c8949d75a69041e6b5375e76901dcd9a023f7aafe9ca287fe63d558837dcc9a -size 23718 diff --git a/rainbow-quox/front/cuffs.webp b/rainbow-quox/front/cuffs.webp new file mode 100644 index 0000000..b8e849b --- /dev/null +++ b/rainbow-quox/front/cuffs.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8f44bf4243d67aea2fc32b905b919afa00e8ecad227425e816b67269260ca61 +size 8304 diff --git a/rainbow-quox/front/eyes.png b/rainbow-quox/front/eyes.png deleted file mode 100644 index 121d181..0000000 --- a/rainbow-quox/front/eyes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:575412468db799eb7dad082cf2c3e5bc1d035da19c99ada2d6a1a4b6d18231e5 -size 2543 diff --git a/rainbow-quox/front/eyes.webp b/rainbow-quox/front/eyes.webp new file mode 100644 index 0000000..db3c69c --- /dev/null +++ b/rainbow-quox/front/eyes.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c407db7a06688de206e8edfff49a6164c4a0ac62dab42c780befa80fb100e3f6 +size 1890 diff --git a/rainbow-quox/front/fins1.png b/rainbow-quox/front/fins1.png deleted file mode 100644 index 427f23a..0000000 --- a/rainbow-quox/front/fins1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f94136fa4f440cd0a7f437aa09ec10ad4a743234364434f3639d50c623fe6740 -size 13888 diff --git a/rainbow-quox/front/fins1.webp b/rainbow-quox/front/fins1.webp new file mode 100644 index 0000000..967f769 --- /dev/null +++ b/rainbow-quox/front/fins1.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7259534ef0f8bc9857a89f11bffcbad8b65f6f54e17de4c43542278bf912847 +size 6438 diff --git a/rainbow-quox/front/fins2.png b/rainbow-quox/front/fins2.png deleted file mode 100644 index b31282f..0000000 --- a/rainbow-quox/front/fins2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d3b2b0d1fb34210e4306ed6d17282b8e88617114810108e0905dcb29857f8d19 -size 14569 diff --git a/rainbow-quox/front/fins2.webp b/rainbow-quox/front/fins2.webp new file mode 100644 index 0000000..8c337fb --- /dev/null +++ b/rainbow-quox/front/fins2.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:142905b5ec5eace81ecbfa9a93482ae8672e55b7962b9c698b9b02fb14543c1e +size 5988 diff --git a/rainbow-quox/front/fins3.png b/rainbow-quox/front/fins3.png deleted file mode 100644 index feac6ff..0000000 --- a/rainbow-quox/front/fins3.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:81d82d665ca0b355af4166f1cc0966e67212418e334915dad24ada05516b006d -size 4093 diff --git a/rainbow-quox/front/fins3.webp b/rainbow-quox/front/fins3.webp new file mode 100644 index 0000000..c70fded --- /dev/null +++ b/rainbow-quox/front/fins3.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:50722592a90c4d8d562eefd5376ac1bd7d07edc72592789fe3b20b24bc06f580 +size 2298 diff --git a/rainbow-quox/front/lines.png b/rainbow-quox/front/lines.png deleted file mode 100644 index c53cdf4..0000000 --- a/rainbow-quox/front/lines.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:889efb643e0688f235bf0284b9492efa7ecc079b804c82d808fdb91a12c9d4fe -size 179826 diff --git a/rainbow-quox/front/lines.webp b/rainbow-quox/front/lines.webp new file mode 100644 index 0000000..7e7046f --- /dev/null +++ b/rainbow-quox/front/lines.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37a4f97523109c4b64f528bdf4eb13bce9e0d91da23ac653e449db4e82b0ed40 +size 79804 diff --git a/rainbow-quox/front/masks.png b/rainbow-quox/front/masks.png deleted file mode 100644 index 5a0ee6b..0000000 --- a/rainbow-quox/front/masks.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3e37e416635756c263a96913e47913a3686a095a3b01f81a5283787a71e89e4b -size 10878 diff --git a/rainbow-quox/front/masks.webp b/rainbow-quox/front/masks.webp new file mode 100644 index 0000000..07a035d --- /dev/null +++ b/rainbow-quox/front/masks.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:326b64b92fc4ccf34d36c39472eac5a8c0b484eb7450af637d2551b92ac81f9c +size 4848 diff --git a/rainbow-quox/front/outer.png b/rainbow-quox/front/outer.png deleted file mode 100644 index 3323174..0000000 --- a/rainbow-quox/front/outer.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a9e7ab5efdee557acd9bb8bcbeeefbcbeda4c31071185b1b0d6f8a26da879fc4 -size 34875 diff --git a/rainbow-quox/front/outer.webp b/rainbow-quox/front/outer.webp new file mode 100644 index 0000000..e070513 --- /dev/null +++ b/rainbow-quox/front/outer.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2abf9b569e88b52b61cadbcf882ead5c8b06128f31c9495f0e50b13b28778aec +size 13222 diff --git a/rainbow-quox/front/pos.json b/rainbow-quox/front/pos.json new file mode 100644 index 0000000..24c65a6 --- /dev/null +++ b/rainbow-quox/front/pos.json @@ -0,0 +1,21 @@ +{ + "belly1": [186, 92], + "belly2": [186, 91], + "claws": [3, 168], + "cuffs": [42, 160], + "eyes": [223, 52], + "eyeshine": [223, 52], + "fins1": [381, 31], + "fins2": [387, 35], + "fins3": [495, 140], + "lines": [1, 0], + "masks": [173, 3], + "outer": [28, 43], + "spines": [372, 23], + "static": [50, 52], + "stripes": [50, 168], + "vitiligo1": [34, 23], + "vitiligo2": [198, 92], + "vitiligo3": [214, 312], + "vitiligo4": [647, 71] +} diff --git a/rainbow-quox/front/spines.png b/rainbow-quox/front/spines.png deleted file mode 100644 index a0a8a0c..0000000 --- a/rainbow-quox/front/spines.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b43c12e8e6c6b6edbdf6ea35f04151f23b26c67a624e86497063b12c6fa4a4cc -size 11263 diff --git a/rainbow-quox/front/spines.webp b/rainbow-quox/front/spines.webp new file mode 100644 index 0000000..cba0a90 --- /dev/null +++ b/rainbow-quox/front/spines.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d41ce8b4cf1ff2f05abfc2b001028f9db29e9c25442607657373b4008b82233 +size 5240 diff --git a/rainbow-quox/front/static.png b/rainbow-quox/front/static.png deleted file mode 100644 index 3ba9e0a..0000000 --- a/rainbow-quox/front/static.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d31dd489e752b5d9fbfb33c67199ab6fe49778fb9d976c06b3695f2bd91ca37b -size 43641 diff --git a/rainbow-quox/front/static.webp b/rainbow-quox/front/static.webp new file mode 100644 index 0000000..49c8711 --- /dev/null +++ b/rainbow-quox/front/static.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:747a5d5b456c54ae31e2eda3279be1e6782b3700133c58e130cc86cee0c4a565 +size 23672 diff --git a/rainbow-quox/front/stripes.png b/rainbow-quox/front/stripes.png deleted file mode 100644 index 39288a6..0000000 --- a/rainbow-quox/front/stripes.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6efe51d45898de27318186ab9a945e434b64c9fccad4d0fe6f3266463916d0f6 -size 43540 diff --git a/rainbow-quox/front/stripes.webp b/rainbow-quox/front/stripes.webp new file mode 100644 index 0000000..cadc60f --- /dev/null +++ b/rainbow-quox/front/stripes.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1327c6808599d2f7a48069cc0171a21213318383a2019f6178a6a092112313b +size 22274 diff --git a/rainbow-quox/front/vitiligo1.png b/rainbow-quox/front/vitiligo1.png deleted file mode 100644 index 494f004..0000000 --- a/rainbow-quox/front/vitiligo1.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:363be71bf2164cffb8f91562bf5913591d73293158f922a5ed9a1917fafb7471 -size 21373 diff --git a/rainbow-quox/front/vitiligo1.webp b/rainbow-quox/front/vitiligo1.webp new file mode 100644 index 0000000..d62fe8f --- /dev/null +++ b/rainbow-quox/front/vitiligo1.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:32f7fe2f08b927c52068039792dd894ff449de8838774b5609a7d62129c2895a +size 8260 diff --git a/rainbow-quox/front/vitiligo2.png b/rainbow-quox/front/vitiligo2.png deleted file mode 100644 index fe6cfc6..0000000 --- a/rainbow-quox/front/vitiligo2.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:935543bd4940a2268ba66bc2cb26859fc42368d5e480ed302c14c679a0c3ae1f -size 5993 diff --git a/rainbow-quox/front/vitiligo2.webp b/rainbow-quox/front/vitiligo2.webp new file mode 100644 index 0000000..ffdb985 --- /dev/null +++ b/rainbow-quox/front/vitiligo2.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a67f1fe1cfb109e2928efadf95c26fdccc65dad09af2d2f1df60db80374757d5 +size 2108 diff --git a/rainbow-quox/front/vitiligo3.png b/rainbow-quox/front/vitiligo3.png deleted file mode 100644 index 16942ab..0000000 --- a/rainbow-quox/front/vitiligo3.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:072c8876a5569801d89db446615f81e3262efd0c6355311b57a4df621b23070f -size 2421 diff --git a/rainbow-quox/front/vitiligo3.webp b/rainbow-quox/front/vitiligo3.webp new file mode 100644 index 0000000..7ca5a11 --- /dev/null +++ b/rainbow-quox/front/vitiligo3.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ec9edac7aaa5ba1125929e711a47dcb004c9e4f65d62820cc30e9cb19fff056 +size 1036 diff --git a/rainbow-quox/front/vitiligo4.png b/rainbow-quox/front/vitiligo4.png deleted file mode 100644 index e1246b9..0000000 --- a/rainbow-quox/front/vitiligo4.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c07b8c4234de1e9a03ffecd54e3805f925d2f5f110181ed0c9f467051c626220 -size 3465 diff --git a/rainbow-quox/front/vitiligo4.webp b/rainbow-quox/front/vitiligo4.webp new file mode 100644 index 0000000..aaca515 --- /dev/null +++ b/rainbow-quox/front/vitiligo4.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb16c83441c0262ae9a37f8b30c849c6a01f403b88419d3a8e0d4e4f3ea54319 +size 1794 diff --git a/rainbow-quox/kra/back.kra b/rainbow-quox/kra/back.kra index a01a414..de27925 100644 --- a/rainbow-quox/kra/back.kra +++ b/rainbow-quox/kra/back.kra @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec8adde036f86be12b8517ff1cdc227ad3dcaaf9e0a0e9e186d060d503fac573 -size 11558980 +oid sha256:30c8f371a2ea5c37b882c14726909a5cdc0626306ad563f19e1d6243f6f95152 +size 10709057 diff --git a/rainbow-quox/kra/front.kra b/rainbow-quox/kra/front.kra index 7fd8554..2dfbb5f 100644 --- a/rainbow-quox/kra/front.kra +++ b/rainbow-quox/kra/front.kra @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:579ca5af9a79a8577f62013418f58c729c646cfda9f2fd2bed54688b59de2ddd -size 11346742 +oid sha256:047b1eb6e703a2c8d67d6ea3a83b942a8636da501b924d8d6a261f3c2f5f1544 +size 11122381 diff --git a/rainbow-quox/style.css b/rainbow-quox/style.css index b5316c5..10c04ba 100644 --- a/rainbow-quox/style.css +++ b/rainbow-quox/style.css @@ -12,12 +12,17 @@ * { transition: none; } } -@keyframes swap { +@keyframes swap1 { 0% { transform: none; } 49% { transform: translateX(-150vw); } 50% { content-visibility: hidden; } - 51% { transform: translateX(150vw); content-visibility: visible; } - 100% { transform: none; } + 100% { content-visibility: hidden; transform: none; } +} + +@keyframes swap2 { + 0% { content-visibility: hidden; transform: translateX(150vw); } + 49% { content-visibility: visible; opacity: 1; } + 100% { transform: none; opacity: 1; } } @keyframes fade-in {