Skip to content

Instantly share code, notes, and snippets.

@porpoiseless
Created July 29, 2020 18:31
Show Gist options
  • Save porpoiseless/bcf9cfdf152efe3d805ae4e48dcdab71 to your computer and use it in GitHub Desktop.
Save porpoiseless/bcf9cfdf152efe3d805ae4e48dcdab71 to your computer and use it in GitHub Desktop.
Color picker for The Next Ithkuilic Language!
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>TNIL Color Picker</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
html {
--border: #909090;
--control-bg: #151515;
--control-fg: #efefef;
--page: #000;
}
body {
min-height: 100vh;
display: flex;
place-items: center;
background: var(--page);
color: #eee;
font: 18px/1.5 "Inter", sans-serif;
font-weight: 100;
font-stretch: 20% 100%;
}
a {
color: darkturquoise;
}
main {
margin: auto;
padding: 1.5rem;
background: var(--control-bg);
color: var(--control-fg);
border: 1px solid var(--border);
border-radius: 2px;
display: flex;
flex-direction: column;
}
input[type="color"] {
border: 1px solid var(--border);
margin-top: 0.5rem;
border-radius: 2px;
width: 100%;
padding: 0;
cursor: pointer;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
input[type="color"]::-webkit-color-swatch-wrapper {
padding: 0;
}
input[type="color"]::-webkit-color-swatch,
input[type="color"]::-moz-color-swatch {
border: none;
}
output {
border-radius: 2px;
min-height: 1.5rem;
margin-top: 0.5rem;
padding: 0.5rem;
text-align: center;
border: 1px solid var(--border);
}
strong {
font-weight: bold;
}
.menu {
position: fixed;
align-self: start;
cursor: pointer;
z-index: 1;
}
.menu:after {
content: "?";
background: var(--control-bg);
color: var(--control-fg);
position: absolute;
border: 1px solid var(--border);
transform: translateY(-100%);
display: flex;
align-items: center;
font-weight: bold;
justify-content: center;
height: 1.5rem;
width: 1.5rem;
border-radius: 50%;
}
.menu-panel {
position: fixed;
top: 0;
left: 0;
height: 100vh;
width: 100%;
transform: translateX(-100%);
/* display: flex;
flex-direction: column; */
padding: 0.5rem;
background: #111;
transition: 350ms;
border-right: 1px solid var(--border);
z-index: 0;
overflow: scroll;
}
.menu-panel > * {
/* max-width: 70ch; */
margin: 1rem 1rem 1rem 2.5rem;
}
#menu-toggle {
position: relative;
height: 0;
width: 0;
opacity: 0;
z-index: 1;
}
#menu-toggle:checked {
z-index: 1;
}
#menu-toggle:checked + .menu-panel {
transform: translateX(0);
transition: 190ms;
}
@media (min-width: 32rem) {
.menu-panel > * {
max-width: 27rem;
margin: 1.5rem auto;
}
}
</style>
<script>
const colorRoots = ["gy", "ňr", "ml", "čw", "ḑr", "lw", "žl", "vm"];
const stems = ["a","ai","ia/oä"];
const grayscale = ["xma-", "cvia/oä-", "cva-", "cvai-", "bva-"];
const colorStems = colorRoots.map(
(root) => stems.map(
(stem) => root + stem + "-"
)).reduce((curr, acc) => [...curr, ...acc], []);
console.log(colorStems);
const hueToRoot = (num) => colorStems[(Math.ceil(num / 15) + 1 )% 24];
function hslToRoot({h, s, l}) {
//
if (s < 0.2) {
return grayscale[Math.floor(4.999 * l)];
} else {
return hueToRoot(h);
}
}
// returns an array of base10 ints
const hexToRGB = (hex) => [
hex.slice(1,3),
hex.slice(3,5),
hex.slice(5,7)
].map((str) => parseInt(str, 16)/255);
function hexStringToHSL (str) {
const rgb = hexToRGB(str);
console.log(rgb);
const min = Math.min(...rgb);
const max = Math.max(...rgb);
let l = (min + max)/2;
let s;
let h;
if (max - min < 0.05) {
s = 0;
h = 0;
} else {
s = l < 0.5 ?
(max - min) / (max + min) :
(max - min ) / (2.0 - max - min);
const [red, green, blue] = rgb;
if (red === max) {
h = (green - blue) / (max - min);
} else if (green === max) {
h = 2.0 + (blue - red)/(max - min);
} else {
//blue is max
h = 4.0 + (red - green)/(max - min);
}
};
return {h: h > 0 ? 60 * h : 360 + 60 *h,
s: s,
l: l};
};
function handleColorInput (event) {
const value = event.target.value;
const hsl = hexStringToHSL(value);
const output = document.querySelector("output");
output.value = hslToRoot(hsl);
console.log(hsl);
const body = document.body;
body.style.setProperty("--page", value);
console.log(value);
}
function setup () {
const input = document.getElementById("color-picker");
input.addEventListener("input", handleColorInput);
handleColorInput({target: input});
}
window.addEventListener("load", setup);
</script>
</head>
<body>
<label class="menu" title="Help">
<input id="menu-toggle" type="checkbox"/>
<aside class="menu-panel">
<h1>Describing Color in the Ithkuil Successor Language</h1>
<p>Color terms in <abbr title="The Next Ithkuilic Language">TNIL</abbr> describe an <a href="https://en.wikipedia.org/wiki/HSL_and_HSV" target="_blank">HSL color space</a>. There are eight roots referring to hue with three stems apiece, meaning that each of the 24 hue lexemes cover 15&deg; on the color wheel. Additionally, there are roots with stems for white and black, plus a root with stems for light, medium, and dark gray.</p>
<p>This converter divides color space into regions corresponding to each of the 11 color-related roots. Pick a color to see the corresponding TNIL root!</p>
<p><strong>Note:</strong> TNIL is even more expressive than this, since it has suffixes for modifying color terms and ways of turning nouns and verbs into color terms by derivation. Maybe some day I'll add suffix recommendations to this thing!</p>
<p>For more information about TNIL color terms, check out the <a href="http://www.ithkuil.net/list_of_roots_v_0_3.pdf#page=142" target="_blank">root listing!</a> To learn more about the Ithkuil successor language, visit <a href="https://www.reddit.com/r/Ithkuil/" target="_blank">our subreddit!</a></p>
</aside>
</label>
<main>
<label for="color-selection">Select a color:</label>
<input name="color-selection" id="color-picker" type="color" value="#000000"/>
<output></output>
</main>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment