lesscielab

How to compute the cubehelix color scheme in Less.js?


I want to compute the cubehelix color scheme in Less so I can tweak some variables. I believe this necessitates CIE L*a*b color system. I ran across Chroma.js which seems like it would work for computing colors, but now I'd like to integrate this into Less.


Solution

  • Mike Bostock has implemented and extended cubehelix in JavaScript as a plugin for the D3.js visualisation library (see examples).

    You can use the code of Bostock's plugin to write a custom function for Less.

    1. Download and unzip the source from github at: https://github.com/less/less.js/archive/master.zip
    2. Run npm install
    3. Create a file called lib/less/functions/cubehelix.js and write down the following content into it:

      var Color = require("../tree/color"),
      functionRegistry = require("./function-registry");
      
      function d3_interpolate(y) {
      return function(a, b) {
            a = a.toHSL();
            b = b.toHSL();
            var radians = Math.PI / 180;
            var ah = (a.h + 120) * radians,
                bh = (b.h + 120) * radians - ah,
                as = a.s,
                bs = b.s - as,
                al = a.l,
                bl = b.l - al;
      
            if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
            if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah;
      
            return function(t) {
              var h = ah + bh * t,
                  l = Math.pow(al + bl * t, y),
                  a = (as + bs * t) * l * (1 - l),
                  cosh = Math.cos(h),
                  sinh = Math.sin(h);
              return "#"
                  + hex(l + a * (-0.14861 * cosh + 1.78277 * sinh))
                  + hex(l + a * (-0.29227 * cosh - 0.90649 * sinh))
                  + hex(l + a * (+1.97294 * cosh));
            };
          };
        }
      
      function hex(v) {
          var s = (v = v <= 0 ? 0 : v >= 1 ? 255 : v * 255 | 0).toString(16);
          return v < 0x10 ? "0" + s : s;
      }
      
      functionRegistry.addMultiple({
      cubehelix: function(y,a,b,t) {
      return new Color(d3_interpolate(y.value)(a,b)(t.value).slice(1),1);
      }   
      });
      
    4. Open the lib/less/function/index.js file and append require("./cubehelix"); to the list of register functions, just before return functions;

    5. Run grunt dist (to create a new version of less.js)

    Now the following Less code:

    p{color: cubehelix(1,red,blue,1);}
    p{color: cubehelix(1,red,blue,0.5);}
    p{color: cubehelix(1, hsl(300,50%,0%), hsl(-240,50%,100%), 0.3);}
    

    outputs:

    p {
      color: #766cfd;
    }
    p {
      color: #21ba40;
    }
    p {
      color: #4c4c4c;
    }