linear interpolation

demonstration of linear interpolation

by not important

HTML

<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script src="http://code.jquery.com/jquery-1.11.0.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="http://mjolnic.github.io/bootstrap-colorpicker/dist/css/bootstrap-colorpicker.min.css">
<script src="http://mjolnic.github.io/bootstrap-colorpicker/dist/js/bootstrap-colorpicker.js"></script>
<div class="container">
    <div class="section-0">
        <div class="row">
            <div class="col-md-12 clearfix variable-input-row">
                <div class="variable-delta-wrapper variable-wrapper input-wrapper click-hint incomplete-hint">
                    <div class="variable-block variable-input variable-delta"></div>
                </div>
                <div class="variable-spacer spacer-charlie"></div>
                <div class="variable-echo-wrapper variable-wrapper output-wrapper click-hint incomplete-hint">
                    <div class="variable-block variable-output variable-echo"></div>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12 section-continue">
                <div class="section-0-complete-wrapper pull-right">
                    <button class="btn section-0-complete" type="button" disabled="disabled">&raquo;</button>
                </div>
            </div>
        </div>
    </div>
    <div class="section-1">
        <div class="row">
            <div class="col-md-12 clearfix variable-input-row">
                <div class="variable-alpha-wrapper variable-wrapper input-wrapper click-hint incomplete-hint">
                    <div class="variable-block variable-input variable-alpha"></div>
                </div>
                <div class="variable-spacer spacer-alpha"></div>
                <div class="variable-bravo-wrapper variable-wrapper input-wrapper click-hint incomplete-hint">
  ...

CSS

body {
    margin-top: 40px;
    -webkit-transform: translate3d(0,0,0);
}

.section-0,
.section-1,
.section-2 {
    width: 315px;
}

.colorpicker {
    margin-top: -30px;
}

.section-1,
.section-2 {
    display: none;
}

.section-continue {
    margin-top: 20px;
}

.variable-block {
    width: 30px;
    height: 30px;
    float: left;
}

.variable-alpha,
.variable-echo,
.variable-foxtrot,
.variable-delta {
    background-color: rgb(212, 63, 58);
}

.variable-bravo,
.variable-golf {
    background-color: rgb(92, 184, 92);
}

.variable-hotel {
    background-color: rgb(66, 139, 202);
}

.variable-charlie,
.variable-india,
.variable-juliet {
    background-color: rgb(255, 255, 255);
}

.variable-spacer {
    float: left;
    height: 30px;
}

.spacer-alpha,
.spacer-charlie,
.spacer-delta,
.spacer-echo,
.spacer-golf {
    width: 90px;
}

.spacer-bravo,
.spacer-foxtrot {
    width: 60px;
}

.variable-input-row {
    margin-bottom: 5px;
    height: 30px;
}

.variable-input {
    cursor: pointer;
}

.variable-input,
.variable-output {
    box-shadow: 0 0 4px rgba(0, 255, 0, 1);
}

.variable-input.incomplete-hint,
.variable-output.incomplete-hint {
    box-shadow: 0 0 4px rgba(0, 0, 0, 1);
}

.variable-bravo {
    -webkit-animation-delay: 0.5s;
}

.demo-area {
    z-index: 1;
    position: relative;
}

.click-hint {
    position: relative;
    z-index: 2;
    margin: -15px;
    display: inline-block;
    float: left;
    border-width: 15px;
    border-color: rgba(0, 255, 0, 0);
    border-style: solid;
    border-radius: 100%;
    -webkit-box-sizing: border-box;

    -webkit-animation: input-hint 3s infinite;
    -webkit-transition-timing-function: ease-in-out;
}

.click-hint.incomplete-hint {
    border-color: rgba(0, 0, 0, 0);
    -webkit-animation: input-hint-incomplete 3s infinite;
}

.click-hint .variable-input {
    -webkit-transform: scale(1);
    box-shadow: 0 0 4px rgba(0, 0, 0, 1);
    -webkit-animation: input-pulse 3s infinite;
   ...

CoffeeScript

linearInterpolate = (startValue, endValue, stepCount) ->
    results = []

    for stepIndex in [0..stepCount]
        results.push startValue + (stepIndex / stepCount) * (endValue - startValue)

    results

colorLerp = (startColor, endColor, stepCount) ->
    stepCount = stepCount - 1
    redComponents = linearInterpolate startColor.red, endColor.red, stepCount
    greenComponents = linearInterpolate startColor.green, endColor.green, stepCount
    blueComponents = linearInterpolate startColor.blue, endColor.blue, stepCount

    results = []

    for componentIndex in [0..stepCount]
        red = Math.round redComponents[componentIndex]
        green = Math.round greenComponents[componentIndex]
        blue = Math.round blueComponents[componentIndex]

        results.push {red, green, blue}

    results

addColorPicker = ($el, colorValue, callback) ->
    $el.colorpicker(
        color: "rgb(#{colorValue.red}, #{colorValue.green}, #{colorValue.blue})"
    ).on 'changeColor', (e) ->
        newColor = e.color.toRGB()
        red = newColor.r
        green = newColor.g
        blue = newColor.b

        $el.css 'background-color', "rgb(#{red}, #{green}, #{blue})"

        callback {red, green, blue}

findColorSolutionAlpha = (startColor, endColor) ->
    drawingContext = $('#figureAlpha').get(0).getContext '2d'

    colorSteps = colorLerp startColor, endColor, 5

    drawingContext.clearRect 0, 0, 30 * colorSteps.length, 30

    for colorStep, colorStepIndex in colorSteps
        drawingContext.fillStyle = "rgb(#{colorStep.red}, #{colorStep.green}, #{colorStep.blue})"
        drawingContext.fillRect colorStepIndex * 30, 0, 30, 30

    solvedColor = colorSteps[2]

    $('.variable-charlie').css 'background-color', "rgb(#{solvedColor.red}, #{solvedColor.green}, #{solvedColor.blue})"

findColorSolutionBravo = (firstColor, secondColor, thirdColor) ->
    drawingContext = $('#figureBravo').get(0).getContext '2d'

    colorStepsAlpha = colorLerp firstColor, secondColor,...