Chroma.js Color Scale Helper

This chroma.js-powered tool is here to help us mastering multi-hued, multi-stops color scales.

by justi

HTML

<script src="https://assets-datawrapper.s3.amazonaws.com/vendor/chroma-js/0.5.2/chroma.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap-responsive.css">
<div class="container"><div class="row"><div class="span8 offset2">
<h2>Chroma.js&nbsp;Color Scale&nbsp;Helper</h2>

<p>This <a href="https://github.com/gka/chroma.js" target="_blank">chroma.js</a>-powered tool is here to help us  <a target="_blank" href="http://vis4.net/blog/posts/mastering-multi-hued-color-scales/">mastering multi-hued, multi-stops color scales</a>.</p>

<div class="row"><div class="form well span8">
    <div class="row">
        <div class="span5">
            <label>Enter <a target="_blank" href="http://www.mcfedries.com/books/cightml/x11color.htm">named colors</a> or hex codes:</label>
            <input id="colors" checked="checked" type="text" value="lightyellow, orange, deeppink, darkred" />
        </div>
        <div class="span3">
            <label>Step count</label>
            <input id="steps" checked="checked" type="number" value="9" />
        </div>
    </div>
    <div class="row">
        <div class="span4">
            <label class="checkbox">
                <input id="bez" type="checkbox"  checked="checked" />
                Bezier interpolation
            </label>
        </div>
        <div class="span4">
            <label class="checkbox">
                <input id="coL" type="checkbox" checked="checked" />
                Correct lightness gradient
            </label>
        </div>
    </div>
</div></div>
<div id="out"></div>

<div id="footer">
    <hr/>
    Created by <a href="http://vis4.net/blog"  target="_blank">Gregor Aisch</a> for the sake of better use of colors in maps and datavis. <a href="http://jsfiddle.net/vis4/cYLZH/" style="color:#bbb">Edit in JSFiddle!</a>
</div>
    </div>
 ...

CSS

body {
 padding: 20px;   
}

h2 {
    font-weight: 300;
}

#steps {
    width: 6em;
    text-align: right;
}

#colors {
    width: 98%;
}


svg {
    margin: 10px 0;
}

svg path {
    stroke: #000;
    stroke-width: 2px;
    fill: none;
    shape-rendering: crispEdges;
}


#out {
    margin-top: 2em;
}

div.gradient {
    padding: 10px 10px 6px;
    border-radius:4px;
    background: Gainsboro;
    text-align: center;
}

pre {
    border: 0;
    background: transparent;
    color: gray;
}

div.gradient div {
    display: inline-block;
    height: 50px;
    color: rgba(0,0,0,0);
}

CoffeeScript

width = $('.span8').width()-20

update = () ->
    bez = $('#bez').prop 'checked'
    coL = $('#coL').prop 'checked'
    colors = $('#colors').val().replace(/(, *| +)/g, ',').split(',')
    steps = +$('#steps').val()
    
    # initialize chroma.scale
    colors = chroma.interpolate.bezier(colors) if bez
    cs = chroma.scale(colors).mode('lab').correctLightness(coL)
    
    # clear display
    $('#out').html('')
    
    # visualize scale
    showScale cs, steps

    serializeUrl()
    

showScale = (cs, steps) ->
    c = $('<div />')
        .css('width', width)
        .addClass('gradient')
        .appendTo('#out')
    cols = []
    for t in (i/(steps-1) for i in [0...steps])
        d = $ '<div />'
        d.css
            width: (100/steps)+'%'
            background: cs(t).hex()
        d.appendTo c
        cols.push cs(t).hex()
    
    showLightnessCurve cs, steps
    
    # copy colors
    $('<pre/>')
        .html('[\'' + cols.join('\', \'') + '\']')
        .appendTo('#out')

showLightnessCurve = (cs, steps) ->
    s = document.createElementNS 'http://www.w3.org/2000/svg','svg'
    s.setAttribute 'width', width+10
    s.setAttribute 'height', 150
    path = document.createElementNS 'http://www.w3.org/2000/svg','path'
    d = ''
    x = 10
    for t in (i/(steps-1) for i in [0...steps])
        y = (102 - cs(t).lab()[0])*1.2
        x += width/steps
        if d == ''
            d = 'M'+[10,y]
        d += ' V'+y
        d += ' H'+x
    path.setAttribute 'd', d    
    s.appendChild path
    $('#out').append(s)

serializeUrl = () ->
    location.hash = '#' + 
        'colors='+$('#colors').val() + '|' +
        'steps='+$('#steps').val() + '|' +
        'bez='+(if $('#bez').prop('checked') then 1 else 0) + '|' +
        'coL='+(if $('#coL').prop('checked') then 1 else 0)
    
unserializeUrl = () ->
    vars = location.hash
        .substr(1)
        .split('|')
    for v in (v.split('=') for v in vars)
        [key,val] = v
        if key ==...