OKLCH

by phloe

HTML

<canvas id="canvas" width="45" height="45"></canvas>

<input id="hueInput" type="range" value="0" min="0" step="0.001" max="360" />
<span id="hueValue">0</span>

CSS

#canvas {
  width: 360px;
  height: 360px;
  _image-rendering: pixelated;
}

JavaScript

const context = canvas.getContext("2d", { colorSpace: "display-p3" });

const maxL = 1;
const maxC = 0.4;
const maxH = 360;

let h = 0, l = 0, c = 0.2;

function update() {
	const { width, height } = canvas;
  for (var y = 0; y < height; y++) {
    l = (1 - (y / height)) * maxL;
    for (var x = 0; x < width; x++) {
      c = (1 - (x / width)) * maxC;
      context.fillStyle = `oklch(${l} ${c} ${h})`;
      context.fillRect(x, y, 1, 1);
    }
  }
}

var timer;
let maxRes = 0;
let res = maxRes;
let minRes = 3;
let maxSize = 360;

function setRes() {
  const size = maxSize / Math.pow(2, res);
  canvas.width = size;
  canvas.height = size;
}

function upRes() {
  if (timer) {
  	timer = clearTimeout(timer);
  }
	if (res > maxRes) {
    setRes();
  	update();
  	timer = setTimeout(upRes, 16);
		res--;
	}
  else {
  	update();
  }
}


hueInput.addEventListener('input', (event) => {
	if (timer) {
  	timer = clearTimeout(timer);
  }
  if (res < minRes) {
    res = minRes;
    setRes();
  }
	timer = setTimeout(upRes, 300);
	h = parseFloat(event.target.value);
  hueValue.innerText = h.toFixed(2);
	update();
});

update();