{hslColor()}+
{rgbColor()} {hslColor()}
diff --git a/src/assets/favicon.ico b/src/assets/favicon.ico new file mode 100644 index 0000000..b836b2b Binary files /dev/null and b/src/assets/favicon.ico differ diff --git a/src/components/color-input.tsx b/src/components/color-input.tsx index f91f5cf..15ceef0 100644 --- a/src/components/color-input.tsx +++ b/src/components/color-input.tsx @@ -1,11 +1,20 @@ import { mergeProps } from "solid-js"; -function ColorInput(props) { +type ColorInputProps = { + label: string; + min: number; + max: number; + value: number; + onInput: (a: number) => void; + step?: number +} + +function ColorInput(props: ColorInputProps) { const options = mergeProps({ step: 1 }, props); - const setValue = (e) => { - let value = parseFloat(e.currentTarget.value); - options.onInput(value); + const setValue = (e: InputEvent) => { + let eventTarget = e.currentTarget as HTMLInputElement; + options.onInput(parseFloat(eventTarget.value)); } return ( diff --git a/src/components/colorer.tsx b/src/components/colorer.tsx index bfa7b37..a143268 100644 --- a/src/components/colorer.tsx +++ b/src/components/colorer.tsx @@ -1,11 +1,74 @@ import { useHslaContext } from "/@/hsla-context"; import ColorInput from "/@lib/color-input"; -function Colorer(props) { +function Colorer() { const [hsla, { setH, setS, setL, setA }] = useHslaContext(); const hslColor = () => `hsla(${hsla().h}, ${hsla().s}%, ${hsla().l}%, ${hsla().a})`; + const rgbColor = () => { + const [r, g, b] = hsl2rgb(hsla().h, hsla().s / 100, hsla().l / 100) + return `rbga(${r}, ${g}, ${b}, ${hsla().a})` + } + + const hsl2rgb = (h: number, s: number, l: number) => { + const defrange = { + h: (h: number) => 0 <= h && h < 360, + s: (s: number) => 0 <= s && s <= 1, + l: (l: number) => 0 <= l && l <= 1 + } + if (!defrange.h(h)) throw "h out of range" + if (!defrange.s(s)) throw "s out of range" + if (!defrange.l(l)) throw "l out of range" + + let c = (1 - Math.abs(2 * l - 1)) * s + let x = c * (1 - Math.abs((h / 60) % 2 - 1)) + let m = l - (c / 2) + + const rgb = (rd: number, gd: number, bd: number) => [ + Math.ceil((rd + m) * 255), + Math.ceil((gd + m) * 255), + Math.ceil((bd + m) * 255) + ] + + if (h < 60) return rgb(c, x, 0) + else if (h < 120) return rgb(x, c, 0) + else if (h < 180) return rgb(0, c, x) + else if (h < 240) return rgb(0, x, c) + else if (h < 300) return rgb(x, 0, c) + else return rgb(c, 0, x) + } + + const rgb2hsl = (r: number, g: number, b: number) => { + const + rd = r / 255, + gd = g / 255, + bd = b / 255, + cmax = Math.max(rd, gd, bd), + cmin = Math.min(rd, gd, bd), + delta = (cmax - cmin), + l = (cmax + cmin) / 2 + + let + h: number = 0, + s: number = 0 + // for this case h and s == 0 + if (delta === 0) + return [h, s, l] + + if (cmax == rd) + h = ((gd - bd) / delta) + (gd < bd ? 6 : 0) + else if (cmax == gd) + h = ((bd - rd) / delta) + 2 + else if (cmax == bd) + h = ((rd - gd) / delta) + 4 + h = 60 * h + + s = delta / (1 - Math.abs(2 * l - 1)) + + return [h, s, l] + } + return (
{hslColor()}+
{rgbColor()} {hslColor()}