hsl rgb color conversion
This commit is contained in:
parent
b67adb823d
commit
1c78ab3522
BIN
src/assets/favicon.ico
Normal file
BIN
src/assets/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
@ -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 (
|
||||
|
@ -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 (
|
||||
<div class="main-container">
|
||||
<div id="colorer">
|
||||
@ -17,7 +80,7 @@ function Colorer(props) {
|
||||
<div class="color-box" style={{
|
||||
"background-color": hslColor()
|
||||
}}></div>
|
||||
<pre>{hslColor()}</pre>
|
||||
<pre>{rgbColor()} {hslColor()}</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"jsxImportSource": "solid-js",
|
||||
"types": ["vite/client"]
|
||||
|
Loading…
Reference in New Issue
Block a user