// random HSL colour
c.fillStyle = 'hsl('+ 360*Math.random() +',100%,50%)';
See
Red is 0°, green is 120° and blue is 240°.
See
- https://mika-s.github.io/javascript/colors/hsl/2017/12/05/generating-random-colors-in-javascript.html
- https://blog.logrocket.com/how-to-manipulate-css-colors-with-javascript-fb547113a1b8/ https://www.alanzucconi.com/wp-content/ql-cache/quicklatex.com-c658c0858afb911a405dfed6a837246b_l3.svg- https://v6.robweychert.com/blog/2019/12/dynamic-color-javascript-hsl/
See
- https://github.com/worksbyscott/Interpolator/blob/main/interpolator.js
- https://gist.github.com/mlocati/7210513
// pass in hex colours, without the #
function interpolateColor(c0, c1, f){
c0 = c0.match(/.{1,2}/g).map((oct)=>parseInt(oct, 16) * (1-f))
c1 = c1.match(/.{1,2}/g).map((oct)=>parseInt(oct, 16) * f)
let ci = [0,1,2].map(i => Math.min(Math.round(c0[i]+c1[i]), 255))
return ci.reduce((a,v) => ((a << 8) + v), 0).toString(16).padStart(6, "0")
}
// using HSL colors
function percentageToColor(percentage, maxHue = 120, minHue = 0) {
const hue = percentage * (maxHue - minHue) + minHue;
return `hsl(${hue}, 100%, 50%)`;
}
// usage: lerpColor('#000000', '#ffffff', 0.5)
function lerpColor(a, b, amount) {
var ah = +a.replace('#', '0x'),
ar = ah >> 16, ag = ah >> 8 & 0xff, ab = ah & 0xff,
bh = +b.replace('#', '0x'),
br = bh >> 16, bg = bh >> 8 & 0xff, bb = bh & 0xff,
rr = ar + amount * (br - ar),
rg = ag + amount * (bg - ag),
rb = ab + amount * (bb - ab);
return '#' + ((1 << 24) + (rr << 16) + (rg << 8) + rb | 0).toString(16).slice(1);
}
// here's a version that just deals with hex literals
// usage: lerpColor(0x000000, 0xffffff, 0.5)
const lerpColor = function(pFrom, pTo, pRatio) {
const ar = (pFrom & 0xFF0000) >> 16,
ag = (pFrom & 0x00FF00) >> 8,
ab = (pFrom & 0x0000FF),
br = (pTo & 0xFF0000) >> 16,
bg = (pTo & 0x00FF00) >> 8,
bb = (pTo & 0x0000FF),
rr = ar + pRatio * (br - ar),
rg = ag + pRatio * (bg - ag),
rb = ab + pRatio * (bb - ab);
return (rr << 16) + (rg << 8) + (rb | 0);
};
// RGB from string
const [r, g, b] = rgbStr.slice(4, -1).split(',').map(Number)
const randomHsl = () => `hsla(${Math.random() * 360}, 100%, 50%, 1)`
const randomRGB = () => `rgb(${[1,2,3].map(x=>Math.random()*256|0)})`
const randomHex = () => '#'+(Math.random()*0xFFFFFF<<0).toString(16);
const randomHex = () => Math.floor(Math.random()*16777215).toString(16);
// https://helderesteves.com/generating-random-colors-js/
function generateRandomColorHex() {
return "#" + ("00000" + Math.floor(Math.random() * Math.pow(16, 6)).toString(16)).slice(-6);
}
function generateRandomColorRgb() {
const red = Math.floor(Math.random() * 256);
const green = Math.floor(Math.random() * 256);
const blue = Math.floor(Math.random() * 256);
return "rgb(" + red + ", " + green + ", " + blue + ")";
}
function generateRandomColorHsl() {
const hue = Math.floor(Math.random() * 360);
const saturation = Math.floor(Math.random() * (100 + 1)) + "%";
const lightness = Math.floor(Math.random() * (100 + 1)) + "%";
return "hsl(" + hue + ", " + saturation + ", " + lightness + ")";
}
function get_random_hsl() {
const rand = (min, max) => min + Math.random() * (max - min),
h = rand(1, 360),
s = rand(0, 100),
l = rand(0, 100);
return 'hsl(' + h + ',' + s + '%,' + l + '%)';
}
const pastels = () => {
const round = Math.round,
randm = Math.random,
n = 127,
r = (round(randm()* n)+n).toString(16),
g = (round(randm()* n)+n).toString(16),
b = (round(randm()* n)+n).toString(16);
return '#'+r+g+b;
}
// Generate vibrant, "evenly spaced" colours (no clustering).
// This is ideal for creating easily distinguishable vibrant colours.
// 30 random hues with step of 12 degrees
const hslToHex = (h,s,l) => {
l /= 100;
const a = s * Math.min(l, 1 - l) / 100;
const f = n => {
const k = (n + h / 30) % 12;
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return Math.round(255 * color).toString(16).padStart(2, '0'); // convert to Hex and prefix "0" if needed
};
return `#${f(0)}${f(8)}${f(4)}`;
}
const rainbow = (deg=12) => {
const hue = Math.floor(Math.random() * 30) * deg;
return hslToHex(hue, 0.9, 0.6);
};
// another version: by Adam Cole, 2011-Sept-14
function rainbow(numOfSteps, step) {
// HSV to RBG adapted from: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
const h = step / numOfSteps;
let r, g, b;
let i = ~~(h * 6);
let f = h * 6 - i;
let q = 1 - f;
switch(i % 6){
case 0: r = 1; g = f; b = 0; break;
case 1: r = q; g = 1; b = 0; break;
case 2: r = 0; g = 1; b = f; break;
case 3: r = 0; g = q; b = 1; break;
case 4: r = f; g = 0; b = 1; break;
case 5: r = 1; g = 0; b = q; break;
}
var c = "#" + ("00" + (~ ~(r * 255)).toString(16)).slice(-2) + ("00" + (~ ~(g * 255)).toString(16)).slice(-2) + ("00" + (~ ~(b * 255)).toString(16)).slice(-2);
return (c);
}
function randomHex() {
const letters = '0123456789ABCDEF';
const color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
const randomHex = function() {
let color = '#', i = 5;
do {
color += "0123456789abcdef".substr(Math.random() * 16,1);
} while (i--);
return color;
}
function randomRgbaString (alpha) {
let r = Math.floor(Math.random() * 255)
let g = Math.floor(Math.random() * 255)
let b = Math.floor(Math.random() * 255)
let a = alpha
return `rgba(${r},${g},${b},${a})`
}
// https://mika-s.github.io/javascript/colors/hsl/2017/12/05/generating-random-colors-in-javascript.html
/
// VERY NICE - even spread of random colours across spectrum!
// - each colour can then be adjusted by saturation/lightness/transparency later
// Usage:
//
// let c = generateHslaColors(50, 100, 1.0, 3)
//
function generateHslaColors (saturation, lightness, alpha, amount) {
let colors = []
let huedelta = Math.trunc(360 / amount)
for (let i = 0; i < amount; i++) {
let hue = i * huedelta
colors.push(`hsla(${hue},${saturation}%,${lightness}%,${alpha})`)
}
return colors
}
const toGreyscale(r,g,b) => {
const brightness = (3*r+4*g+b)>>>3;
return {
r: brightness,
g: brightness,
b: brightness,
}
}
}
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param {number} h The hue
* @param {number} s The saturation
* @param {number} l The lightness
* @return {Array} The RGB representation
*/
function hslToRgb(h, s, l){
var r, g, b;
if(s == 0){
r = g = b = l; // achromatic
}else{
var hue2rgb = function hue2rgb(p, q, t){
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
/**
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h, s, and l in the set [0, 1].
*
* @param {number} r The red color value
* @param {number} g The green color value
* @param {number} b The blue color value
* @return {Array} The HSL representation
*/
function rgbToHsl(r, g, b){
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if(max == min){
h = s = 0; // achromatic
}else{
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max){
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [h, s, l];
}
// Shortest but precise
// input: h in [0,360] and s,v in [0,1] - output: r,g,b in [0,1]
function hsl2rgb(h,s,l)
{
let a=s*Math.min(l,1-l);
let f= (n,k=(n+h/30)%12) => l - a*Math.max(Math.min(k-3,9-k,1),-1);
return [f(0),f(8),f(4)];
}
// Example:
// hslToHex(360, 100, 50) // "#ff0000" -> red
//
function hslToHex(h, s, l) {
l /= 100;
const a = s * Math.min(l, 1 - l) / 100;
const f = n => {
const k = (n + h / 30) % 12;
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return Math.round(255 * color).toString(16).padStart(2, '0'); // convert to Hex and prefix "0" if needed
};
return `#${f(0)}${f(8)}${f(4)}`;
}
// rgb param is any array [0,0,255]
// returns HSLA colour
function rgbToHsla(rgb) {
var a, add, b, diff, g, h, hue, l, lum, max, min, r, s, sat;
r = parseFloat(rgb[0]) / 255;
g = parseFloat(rgb[1]) / 255;
b = parseFloat(rgb[2]) / 255;
max = Math.max(r, g, b);
min = Math.min(r, g, b);
diff = max - min;
add = max + min;
hue = min === max ? 0 : r === max ? ((60 * (g - b) / diff) + 360) % 360 : g === max ? (60 * (b - r) / diff) + 120 : (60 * (r - g) / diff) + 240;
lum = 0.5 * add;
sat = lum === 0 ? 0 : lum === 1 ? 1 : lum <= 0.5 ? diff / add : diff / (2 - add);
h = Math.round(hue);
s = Math.round(sat * 100);
l = Math.round(lum * 100);
a = parseFloat(rgb[3]) || 1;
return [h, s, l, a];
}
// Returns the color as an array of [r, g, b, a] -- all range from 0 - 255
// color must be a valid canvas fillStyle. This will cover most anything
// you'd want to use.
// Examples:
// colorToRGBA('red') # [255, 0, 0, 255]
// colorToRGBA('#f00') # [255, 0, 0, 255]
function colorToRGBA(color) {
var cvs, ctx;
cvs = document.createElement('canvas');
cvs.height = 1;
cvs.width = 1;
ctx = cvs.getContext('2d');
ctx.fillStyle = color;
ctx.fillRect(0, 0, 1, 1);
return ctx.getImageData(0, 0, 1, 1).data;
}
// ...or just
function standardize_color(str) {
var ctx = document.createElement('canvas').getContext('2d');
ctx.fillStyle = str;
return ctx.fillStyle;
}
// Turns a number (0-255) into a 2-character hex number (00-ff)
function byteToHex(num) {
return ('0'+num.toString(16)).slice(-2);
}
// Convert any CSS color to a hex representation
// Examples:
// colorToHex('red') # '#ff0000'
// colorToHex('rgb(255, 0, 0)') # '#ff0000'
function colorToHex(color) {
let rgba, hex;
rgba = colorToRGBA(color);
hex = [0,1,2].map(function(idx) { return byteToHex(rgba[idx]); }).join('');
return "#"+hex;
}
function nameToRGB(name) {
// Create fake div
let fakeDiv = document.createElement("div");
fakeDiv.style.color = name;
document.body.appendChild(fakeDiv);
// Get color of div
let cs = window.getComputedStyle(fakeDiv),
pv = cs.getPropertyValue("color");
// Remove div after obtaining desired color value
document.body.removeChild(fakeDiv);
return pv;
}
const rgb2hex = (rgb) => {
return (rgb && rgb.length === 3) ? "#" +
("0" + parseInt(rgb[0],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2],10).toString(16)).slice(-2) : '';
}
function hexToHSL(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
r = parseInt(result[1], 16);
g = parseInt(result[2], 16);
b = parseInt(result[3], 16);
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if(max == min){
h = s = 0; // achromatic
}else{
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max){
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
var HSL = new Object();
HSL['h']=h;
HSL['s']=s;
HSL['l']=l;
return HSL;
}
function rgbToHsl(r, g, b) {
r /= 255; g /= 255; b /= 255;
let max = Math.max(r, g, b);
let min = Math.min(r, g, b);
let d = max - min;
let h;
if (d === 0) h = 0;
else if (max === r) h = (g - b) / d % 6;
else if (max === g) h = (b - r) / d + 2;
else if (max === b) h = (r - g) / d + 4;
let l = (min + max) / 2;
let s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
return [h * 60, s, l];
}
function hsl2rgb(h,s,l) {
let a= s*Math.min(l,1-l);
let f= (n,k=(n+h/30)%12) => l - a*Math.max(Math.min(k-3,9-k,1),-1);
return [f(0),f(8),f(4)];
}
function hslToRgb(h, s, l) {
let c = (1 - Math.abs(2 * l - 1)) * s;
let hp = h / 60.0;
let x = c * (1 - Math.abs((hp % 2) - 1));
let rgb1;
if (isNaN(h)) rgb1 = [0, 0, 0];
else if (hp <= 1) rgb1 = [c, x, 0];
else if (hp <= 2) rgb1 = [x, c, 0];
else if (hp <= 3) rgb1 = [0, c, x];
else if (hp <= 4) rgb1 = [0, x, c];
else if (hp <= 5) rgb1 = [x, 0, c];
else if (hp <= 6) rgb1 = [c, 0, x];
let m = l - c * 0.5;
return [
Math.round(255 * (rgb1[0] + m)),
Math.round(255 * (rgb1[1] + m)),
Math.round(255 * (rgb1[2] + m))
];
}