block by nitaku 7623b0d6fefc4e505392

HCL linear rainbow scales (for d3)

Full Screen

-

index.js

(function() {
  var hcl_linear_rainbow, height, n, palettes, scales, svg, width;

  hcl_linear_rainbow = function() {
    var chroma_range, domain, hue_range, luminance_range, scale;

    domain = [0, 1];
    hue_range = [340, 340 - 480];
    chroma_range = [0, 40];
    luminance_range = [0, 100];
    scale = function(x) {
      var ext, xn;

      ext = domain[1] - domain[0];
      xn = (x - domain[0]) / ext;
      return d3.hcl(hue_range[0] + (hue_range[1] - hue_range[0]) * xn, chroma_range[0] + (chroma_range[1] - chroma_range[0]) * (1 - Math.pow(1 - 2 * xn, 2)), luminance_range[0] + (luminance_range[1] - luminance_range[0]) * xn);
    };
    scale.domain = function(x) {
      if (!arguments.length) {
        return domain;
      }
      domain = x;
      return scale;
    };
    scale.hue_range = function(x) {
      if (!arguments.length) {
        return hue_range;
      }
      hue_range = x;
      return scale;
    };
    scale.chroma_range = function(x) {
      if (!arguments.length) {
        return chroma_range;
      }
      chroma_range = x;
      return scale;
    };
    scale.luminance_range = function(x) {
      if (!arguments.length) {
        return luminance_range;
      }
      luminance_range = x;
      return scale;
    };
    return scale;
  };

  scales = [hcl_linear_rainbow(), hcl_linear_rainbow().hue_range([340 - 480, 340]).luminance_range([100, 0]), hcl_linear_rainbow().hue_range([0, 0]), hcl_linear_rainbow().hue_range([0, 0 + 50]), hcl_linear_rainbow().hue_range([0, 0 + 100]), hcl_linear_rainbow().hue_range([90, 90 + 180]), hcl_linear_rainbow().hue_range([90, 90 + 180]).luminance_range([5, 95]).chroma_range([10, 40]), hcl_linear_rainbow().hue_range([-90, -90 + 180]), hcl_linear_rainbow().hue_range([-90, -90 + 180]).chroma_range([0, 35]), hcl_linear_rainbow().hue_range([-90, -90 + 180]).chroma_range([0, 20])];

  scales.forEach(function(scale) {
    return scale.domain([0, 255]);
  });

  n = scales.length;

  svg = d3.select('svg');

  width = svg.node().getBoundingClientRect().width - 20;

  height = svg.node().getBoundingClientRect().height - 10;

  palettes = svg.selectAll('.palette').data(scales).enter().append('g').attr({
    "class": 'palette',
    transform: function(d, i) {
      return "translate(10," + (10 + i * height / n) + ")";
    }
  });

  palettes.selectAll('.band').data(d3.range(256)).enter().append('rect').attr({
    "class": 'band',
    x: function(d, i) {
      return i * width / 256;
    },
    width: width / 256,
    height: height / n - 10,
    fill: function(d) {
      return d3.select(this.parentNode).datum()(d);
    }
  });

}).call(this);

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="description" content="HCL linear rainbow scales (for d3)" />
    <title>HCL linear rainbow scales (for d3)</title>
    <link rel="stylesheet" href="index.css">
    <script src="//d3js.org/d3.v3.min.js"></script>
</head>
<body>
  <svg height="500" width="960"></svg>
  
  <script src="index.js"></script>
</body>
</html>

index.coffee

hcl_linear_rainbow = () ->
  # H and L are linear, C is quadratic
  domain = [0,1]
  hue_range = [340, 340-480]
  chroma_range = [0, 40]
  luminance_range = [0, 100]
  
  scale = (x) ->
    ext = domain[1]-domain[0]
    xn = (x-domain[0]) / ext
    return d3.hcl(hue_range[0] + (hue_range[1]-hue_range[0])*xn, chroma_range[0] + (chroma_range[1]-chroma_range[0]) * (1 - Math.pow(1 - 2*xn, 2) ), luminance_range[0] + (luminance_range[1]-luminance_range[0]) *xn)
    
  scale.domain = (x) ->
    return domain if(!arguments.length)
    domain = x
    return scale
  
  scale.hue_range = (x) ->
    return hue_range if(!arguments.length)
    hue_range = x
    return scale
  
  scale.chroma_range = (x) ->
    return chroma_range if(!arguments.length)
    chroma_range = x
    return scale
  
  scale.luminance_range = (x) ->
    return luminance_range if(!arguments.length)
    luminance_range = x
    return scale
         
  return scale

scales = [
  hcl_linear_rainbow(),
  hcl_linear_rainbow().hue_range([340-480,340]).luminance_range([100,0]),
  hcl_linear_rainbow().hue_range([0,0]),
  hcl_linear_rainbow().hue_range([0,0+50]),
  hcl_linear_rainbow().hue_range([0,0+100]),
  hcl_linear_rainbow().hue_range([90,90+180]),
  hcl_linear_rainbow().hue_range([90,90+180]).luminance_range([5,95]).chroma_range([10,40]),
  hcl_linear_rainbow().hue_range([-90,-90+180]),
  hcl_linear_rainbow().hue_range([-90,-90+180]).chroma_range([0,35]),
  hcl_linear_rainbow().hue_range([-90,-90+180]).chroma_range([0,20])
]
scales.forEach (scale) -> scale.domain([0,255])
n = scales.length

svg = d3.select('svg')
width = svg.node().getBoundingClientRect().width - 20
height = svg.node().getBoundingClientRect().height - 10

palettes = svg.selectAll('.palette')
    .data(scales)
  .enter().append('g')
    .attr
      class: 'palette'
      transform: (d,i) -> "translate(10,#{10+i*height/n})"

palettes.selectAll('.band')
    .data(d3.range(256))
  .enter().append('rect')
    .attr
      class: 'band'
      x: (d,i) -> i*width/256
      width: width/256
      height: height/n-10
      fill: (d) -> d3.select(this.parentNode).datum()(d)
    

index.css

html, body {
  padding: 0;
  margin: 0;
}

svg {
  background: white;
}

.band {
  shape-rendering: crispEdges;
}