JSFiddle - React, Tailwind, and code Playground
HTML
<div>
<div class="float-left">
L<input id="l-in" class="num" type="range" min="0" max="100" value="50.0" step="0.1"/>
<span id="l-out">50</span><br />
A<input id="a-in" class="num" type="range" min="-128" max="128" value="0.0" step="0.1"/>
<span id="a-out">0</span><br />
B<input id="b-in" class="num" type="range" min="-128" max="128" value="0.0" step="0.1"/>
<span id="B-out">0</span><br />
<br />
XYZ = <span id="x-out"></span>, <span id="y-out"></span>, <span id="z-out"></span>
<br /><br />
R<input id="R-in" class="rgb-in" type="range" min="0" max="255" value="119" /><span id="r-out"></span><br />
G<input id="G-in" class="rgb-in" type="range" min="0" max="255" value="119" /><span id="g-out"></span><br />
B<input id="B-in" class="rgb-in" type="range" min="0" max="255" value="119" /><span id="b-out"></span><br />
</div>
<div class="float-left">
<div id="pv" class="preview"></div>
</div>
<div class="clear">
<canvas id="cnv" width="256" height="256"></canvas>
</div>
</div>
SCSS
.num, .rgb-in {
width:20em;
margin:0 0.25em;
}
.float-left {
float: left;
}
.clear {
clear: both;
}
.preview {
margin: 2em;
width: 100px;
height: 100px;
border: black solid 1px;
}
canvas {
cursor: crosshair;
}
CoffeeScript
class ColorLAB
constructor: (@l, @a, @b) ->
_THRESHOLD = 6 / 29
_FACTOR = 3 * (Math.pow (6 / 29), 2)
_CONSTANT = 4 / 29
_f = (t) ->
if t > _THRESHOLD
Math.pow t, 3
else
_FACTOR * (t - _CONSTANT)
asXyz: (white=D65) ->
lf = (@l + 16) / 116
new ColorXYZ((white.x * _f lf + @a / 500), (white.y * _f lf), (white.z * _f lf - @b / 200))
asRgb: ->
@asXyz().asRgb()
class ColorXYZ
constructor: (@x, @y, @z) ->
_THRESHOLD = Math.pow (6 / 29), 3
_FACTOR = (Math.pow (29 / 6), 2) / 3
_CONSTANT = 4 / 29
_f = (t) ->
if t > _THRESHOLD
Math.pow t, 1/3
else
_FACTOR * t + _CONSTANT
asLab: (white=D65) ->
fx = _f @x / white.x
fy = _f @y / white.y
fz = _f @z / white.z
new ColorLAB 116 * fy - 16, 500 * (fx - fy), 200 * (fy - fz)
_gamma = (c) ->
if c < 0.0031308
12.92 * c
else
1.055 * (Math.pow c, 1 / 2.4) - 0.055
asRgb: ->
r = ( 3.2406 * @x - 1.5372 * @y - 0.4986 * @z) / 100
g = (-0.9689 * @x + 1.8758 * @y + 0.0415 * @z) / 100
b = ( 0.0557 * @x - 0.2040 * @y + 1.0570 * @z) / 100
r = 255 * _gamma r
g = 255 * _gamma g
b = 255 * _gamma b
new ColorRGB r, g, b
class ColorRGB
constructor: (@r, @g, @b) ->
is_in_gamut: ->
@r >= 0 and @r <= 255 and
@g >= 0 and @g <= 255 and
@b >= 0 and @b <= 255
_igamma = (c) ->
if c < 0.04045
c / 12.92
else
Math.pow ((c + 0.055) / 1.055), 2.4
asXyz: ->
lr = _igamma @r / 255
lg = _igamma @g / 255
lb = _igamma @b / 255
x = 0.4124 * lr + 0.3576 * lg + 0.1805 * lb
y = 0.2126 * lr + 0.7152 * lg + 0.0722 * lb
z = 0.0193 * lr + 0.1192 * lg + 0.9502 * lb
new ColorXYZ 100 * x, 100 * y, 100 * z
asLab: ->
@asXyz().asLab()
D65 = new ColorXYZ 95.047, 100.00, 108.883
toHex = (input, length) ->
output = input.toString(16)
while output.length < length
output = '0' + output
output
timeout =...