Lch color gradient picker

by Gregor Aisch

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/chroma-js/0.5.2/chroma.min.js"></script>
<h2>Lch color gradient picker</h2>
<div class="row">
    <div class="column"> <b>From:</b> L:<span class="l0"></span>, c:<span class="c0"></span>, h:<span class="h0"></span>

        <br/>L
        <input id="l0" value="111" type="range" min="0" max="140" />
        <br/>c:
        <input id="c0" value="35" type="range" min="0" max="100" />
        <br/>h:
        <input id="h0" value="58" type="range" min="0" max="360" /><br />
        
        hex: <input type="text" id="x0" />
    </div>
    <div class="column"> <b>To:</b> L:<span class="l1"></span>, c:<span class="c1"></span>, h:<span class="h1"></span>

        <br/>L
        <input id="l1" value="40" type="range" min="0" max="140" />
        <br/>c:
        <input id="c1" value="64" type="range" min="0" max="100" />
        <br/>h:
        <input id="h1" value="223" type="range" min="0" max="360" />
        
        <br />hex: <input type="text" id="x1" />
    </div>
</div>

<div class="row">
    <b># of colors:</b>
    <input id="num" type="number" value="7" style="width:3em" /> 
    
</div>
<div class="row"><b>Gradient colors, different interpolation:</b>
    <div class="output"></div>
</div>

<p>Made by <a href="http://driven-by-data.net">Gregor Aisch</a></p>

CSS

body {
    font: 400 15px/24px Helvetica;
}
.row { margin-bottom: 15px }
.column { width: 200px; display: inline-block; }
h2 {
    font-weight:300;
}
label {
    position: absolute;
    left:12px;
    color:#fff;
    font-weight: 300;
    line-height:22px
}
p {
    width: 500px;
}
input[type=text] { width: 9ex; }

JavaScript

function update(e) {

    $('.output').html('');
    
    var cs = chroma.scale([c(0), c(1)])
            .domain([0,1], $('#num').val()),
        domain = cs.domain();

    $.each(['lab','lch','rgb','hsv'], function(i, mode) {
        var clm = $('<div>'+mode.toUpperCase()+'</div>')
                .css({width:'8em', display:'inline-block'})
                   .appendTo('.output');
        cs.mode(mode);
        $.each(domain, function(i) {
            if (!i) return;
            var center = cs((domain[i]+domain[i-1])*0.5);
            $('<div>'+center.hex()+'</div>')
                .css({
                    'border-left': '2em solid '+center.hex(),
                    'padding-left': 5, margin: '0 0 2px'
                })
                .appendTo(clm);
        });
    });
    
    function c(i) {
        
        var l = Number($('#l' + i).val()),
            c = Number($('#c' + i).val()),
            h = Number($('#h' + i).val()),
            x, $x = $('#x'+i);
        if (e && $x.get(0) == e.target) {
            // hex has priority
            x = $x.val();
            var t = chroma(x).lch();
            l = t[0];
            c = t[1];
            h = t[2];
            $('#l' + i).val(l);
            $('#c' + i).val(c);
            $('#h' + i).val(h);
        } else {
            x = chroma(l,c,h,'lch').hex();
        }
        $('.l' + i).text(Math.round(l));
        $('.c' + i).text(Math.round(c));
        $('.h' + i).text(Math.round(h));
        $x.val(x);
        return chroma.lch(l, c, h);
    }
}


$('input,select').change(update);
update();

if (!(function() { var i = document.createElement("input"); i.setAttribute('type','range'); return i.type !== 'text'; })()) {
   $('<p/>').appendTo('body').text('Hint: open this page in Chrome browser to enjoy the awesomeness of the  HTML5 range input slider...'); 
}