UNPKG

colorjs.io

Version:

Color space agnostic color manipulation library

156 lines (143 loc) 7.27 kB
<!DOCTYPE html> <html> <head> <title>Interpolation &bull; Color.js</title> <meta name="viewport" content="width=device-width" /> <link rel="shortcut icon" href="../logo.svg"> <link rel="stylesheet" href="../assets/css/style.css"> <script src="../color.js" type="module"></script> <link rel="stylesheet" href="../assets/css/docs.css" /> </head> <body class="language-js"> <header> <nav> <a href=".." class="logo"><h1 class="logo"><img src="../logo.svg" alt="Color.js"></h1></a> <a href="../get/">Get<span class="wide"> Color.js</span></a> <a href="../docs/">Docs</a> <a href="../api/">API</a> <a href="../notebook/">Play!</a> <a href="../apps/">Demos</a> <a href="../tests/" class="footer">Tests</a> <a href="https://github.com/LeaVerou/color.js">GitHub</a> <a href="https://github.com/LeaVerou/color.js/issues/new" class="footer">File bug</a> </nav> <h1>Interpolation</h1> </header> <main> <aside id="toc"> <ul> <li><a href="the-color-object.html">The Color object</a></li> <li><a href="spaces.html">Supported color spaces</a></li> <li><a href="color-difference.html">Color difference</a></li> <li><a href="manipulation.html">Color manipulation</a></li> <li><a href="gamut-mapping.html">Gamut Mapping</a></li> <li><a href="interpolation.html">Interpolation</a></li> <li><a href="adaptation.html">Chromatic Adaptation</a></li> <li><a href="output.html">Output</a></li> </ul> </aside> <h2 id="ranges">Ranges</h2> <p><a href="../api/#Color#range"><code>color.range()</code></a> and <a href="../api/#Color.range"><code>Color.range()</code></a> are at the core of Color.js’ interpolation engine. They give you a function that accepts a number and returns a color. For numbers in the range 0 to 1, the function <em>interpolates</em>; for numbers outside that range, the function <em>extrapolates</em> (and thus, may not return the results you expect):</p> <pre><code class="js language-js"> let color = new Color("p3", [0, 1, 0]); let redgreen = color.range("red", { space: "lch", // interpolation space outputSpace: "srgb" }); redgreen(.5); // midpoint</code></pre> <p>Percentages (0 to 100%) should be converted to numbers (0 to 1).</p> <p>The <code>space</code> parameter controls the <a href="spaces.html">color space</a> interpolation occurs in, and defaults to Lab. Colors do not need to be in that space, they will be converted for interpolation. The interpolation space can make a big difference in the result:</p> <pre><code class="js language-js">let c1 = new Color("rebeccapurple"); let c2 = new Color("lch", [85, 100, 85]); c1.range(c2); // lab c1.range(c2, {space: "lch"}); c1.range(c2, {space: "srgb"}); // gamma corrected sRGB c1.range(c2, {space: "xyz"}); // XYZ, same result as linear RGB c1.range(c2, {space: "hsl"}); c1.range(c2, {space: "hwb"});</code></pre> <p>Note that for color spaces with a hue angle there are multiple ways to interpolate, which can produce drastically different results. The <code>hue</code> argument is inspired by <a href="https://drafts.csswg.org/css-color-5/#hue-adjuster">the hue-adjuster in CSS Color 5</a>.</p> <pre><code class="js language-js">let c1 = new Color("rebeccapurple"); c1.lch; let c2 = new Color("lch", [85, 85, 85 + 720]); c1.range(c2, {space: "lch", hue: "longer"}); c1.range(c2, {space: "lch", hue: "shorter"}); c1.range(c2, {space: "lch", hue: "increasing"}); c1.range(c2, {space: "lch", hue: "decreasing"}); c1.range(c2, {space: "lch", hue: "raw"}); c1.range(c2, {space: "lch"}); // default is "shorter"</code></pre> <p>Range interpolates between colors as they were at the time of its creation. If you change the colors afterwards, the range will not be affected:</p> <pre><code class="js language-js"> let color = new Color("red"); let color2 = new Color("black"); let gradient = color.range(color2); color.coords[1] = 1; color2.coords[2] = 1; gradient(.5); gradient = color.range(color2); gradient(.5);</code></pre> <p>Interpolating between a coordinate and <code>NaN</code> keeps that coordinate constant. This is useful for achromatic transitions:</p> <pre><code class="js language-js">let lime = new Color("p3", [0, 1, 0]); let white = new Color("lch", [100, 0, 0]); let white2 = new Color("lch", [100, 0, NaN]); let limewhite = lime.range(white, {space: "lch"}); let limewhite2 = lime.range(white2, {space: "lch"}); // Two kinds of fade out to transparent lime.range(new Color("transparent")); lime.range(new Color(lime.space, [NaN, NaN, NaN], 0), {space: lime.space});</code></pre> <p>You can use the <code>progression</code> parameter to customize the progression and make it non-linear:</p> <pre><code class="js language-js"> let r = new Color("lch(50 50 0)").range("lch(90 50 20)"); Color.range(r, {progression: p =&gt; p ** 3});</code></pre> <p>Note that you can use <code>Color.range(rangeFunction)</code> to modify a range after it has been created, as you can see in the example above. This produces a new range, and leaves the old one unaffected.</p> <h2 id="interpolation-by-discrete-steps">Interpolation by discrete steps</h2> <p><a href="../api/#Color#steps"><code>color.steps()</code></a> and <a href="../api/#Color.steps"><code>Color.steps()</code></a> give you an array of discrete steps.</p> <pre><code class="js language-js"> let color = new Color("p3", [0, 1, 0]); color.steps("red", { space: "lch", outputSpace: "srgb", maxDeltaE: 3, // max deltaE between consecutive steps (optional) steps: 10 // min number of steps });</code></pre> <p>By default, the deltaE76 function is used.</p> <h2 id="mixing-colors">Mixing colors</h2> <p>Interpolation can be used to create color mixtures, in any desired proportion, between two colors.</p> <p>Shortcut for specific points in the range:</p> <pre><code class="js language-js"> let color = new Color("p3", [0, 1, 0]); let redgreen = color.mix("red", .5, {space: "lch", outputSpace: "srgb"}); let reddishGreen = color.mix("red", .25, {space: "lch", outputSpace: "srgb"});</code></pre> <p>Static syntax, for one-off mixing:</p> <pre><code class="js language-js"> Color.mix("color(display-p3 0 1 0)", "red", .5);</code></pre> <footer> <a href="../notebook/index.html?storage=https://github.com/leaverou/color.js/docs/interpolation.md" class="edit-page" target="_blank"> Edit this page on Color Notebook </a> </footer> </main> <footer> From <a href="http://lea.verou.me">Lea Verou</a> (co-editor of CSS Color 5) and <a href="https://svgees.us">Chris Lilley</a> (co-editor of CSS Color 3, 4, and 5; W3C representative to ICC) <nav> <a href="../get/">Get<span class="wide"> Color.js</span></a> <a href="../docs/">Docs</a> <a href="../api/">API</a> <a href="../notebook/">Play!</a> <a href="../apps/">Demos</a> <a href="../tests/" class="footer">Tests</a> <a href="https://github.com/LeaVerou/color.js">GitHub</a> <a href="https://github.com/LeaVerou/color.js/issues/new" class="footer">File bug</a> </nav> </footer> <script src="../assets/js/prism.js"></script> <script src="https://blissfuljs.com/bliss.shy.js"></script> <script src="https://live.prismjs.com/src/prism-live.js?load=javascript" async></script> <script src="../assets/js/index.js" type="module"></script> </body> </html>