<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/2.1.0/chroma.min.js"></script>
</head>
<body>
<p>
A quick experiment with different interpolation
strategies in Lch. See JS for notes.
</p>
<div><span>Linear</span><div id="box0" class="box"></div></div>
<div><span>Corrected</span><div id="box1" class="box"></div></div>
</body>
</html>
.box > * {
width: 1.1%;
height: 100%;
display: block;
position: absolute;
top: 0;
background: currentColor;
}
.box {
position: relative;
height: 1em;
border: 1px solid black;
flex-grow: 1;
}
body > div {
display: flex;
margin: 1px 0;
font-size:30px;
line-height: 1;
}
span {
width: 4.5em;
}
// Experimenting with different interpolation
// strategies in Lch
var lch0 = [50, 120, 0];
var lch1 = [50, 0, 180];
function interpolate(a, b, t, linear) {
var l0 = a[0];
var l1 = b[0];
var c0 = a[1];
var c1 = b[1];
var h0 = a[2];
var h1 = b[2];
var ln = l0 + (l1 - l0)*t;
var cn = c0 + (c1 - c0)*t;
var hn;
if (linear) {
// Naive linear interpolation of hue
// no good when chroma at either end is mismatched.
hn = h0 + (h1 - h0)*t;
} else {
// Mike's awful maths below. We don't want "t" to linearly
// interpolate from 0..1, we want a curve: t^p, where p!=1
//
// n = contribution of color c1 to the hue of the gradient:
// 0 when chroma(c1) is 0
// 0.5 when chroma(c0) == chroma(c1)
// 1 when chrome(c0) is 0
//
// then p is exponent so when:
// n=0, p=∞
// n=0.5, p=1
// n=1, p=0
//
// This looks like a tangent to me!
// Bang it in, see what happens.
//
var n = c1 + c0 === 0 ? 0 : c1 / (c1+c0);
var p = Math.tan(Math.PI * (1 - n) / 2);
hn = h0 + (h1 - h0) * Math.pow(t, p);
}
return chroma.lch(ln, cn, hn);
}
function loader() {
var box = document.getElementById("box0");
var max = 99;
for (var i=0;i<=max;i++) {
var e = document.createElement("div");
e.style.color = interpolate(lch0, lch1, i / max, true).hex();
e.style.left = i + "%";
box.appendChild(e);
}
var box = document.getElementById("box1");
var max = 99;
for (var i=0;i<=max;i++) {
var e = document.createElement("div");
e.style.color = interpolate(lch0, lch1, i / max, false).hex();
e.style.left = i + "%";
box.appendChild(e);
}
}
window.addEventListener("DOMContentLoaded", loader);
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |