make-random-color
Version:
A simple and flexible npm package for generating random color codes in various formats.
212 lines (190 loc) • 7.3 kB
JavaScript
// index.js
function mulberry32(seed) {
return function () {
let t = (seed += 0x6d2b79f5);
t = Math.imul(t ^ (t >>> 15), t | 1);
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
function generateRandomNumber(min, max, random) {
return Math.floor(random() * (max - min + 1)) + min;
}
function generateRandomHexColor(random) {
return '#' + Math.floor(random() * 0x1000000).toString(16).padStart(6, '0');
}
function generateRandomRGBColor(min, max, alpha, random) {
const red = generateRandomNumber(min, max, random);
const green = generateRandomNumber(min, max, random);
const blue = generateRandomNumber(min, max, random);
return alpha
? `rgba(${red},${green},${blue},${random().toFixed(2)})`
: `rgb(${red},${green},${blue})`;
}
function generateRandomHSLColor(alpha, random) {
const hue = generateRandomNumber(0, 360, random);
const saturation = generateRandomNumber(0, 100, random);
const lightness = generateRandomNumber(0, 100, random);
return alpha
? `hsla(${hue},${saturation}%,${lightness}%,${random().toFixed(2)})`
: `hsl(${hue},${saturation}%,${lightness}%)`;
}
function generateRandomColor(options = {}) {
const { format = 'hex', min = 0, max = 255, alpha = false, seed = null } = options;
const random = seed ? mulberry32(seed) : Math.random;
switch (format) {
case 'rgb':
return generateRandomRGBColor(min, max, alpha, random);
case 'hsl':
return generateRandomHSLColor(alpha, random);
default:
return generateRandomHexColor(random);
}
}
function generateRandomGradientColors(options = {}) {
const { format = 'hex', count = 2, min = 0, max = 255, alpha = false, seed = null } = options;
const random = seed ? mulberry32(seed) : Math.random;
return Array.from({ length: count }, () =>
generateRandomColor({ format, min, max, alpha, seed: random() })
);
}
function generateRandomColorFamily(options = {}) {
const {
format = 'hex',
count = 5,
min = 0,
max = 255,
alpha = false,
seed = null,
hueRange = 30,
saturationRange = 20,
lightnessRange = 20,
} = options;
const baseColor = generateRandomColor({ format: 'hsl', min, max, alpha, seed });
const [hue, saturation, lightness] = baseColor.match(/\d+/g);
const random = seed ? mulberry32(seed) : Math.random;
return [
baseColor,
...Array.from({ length: count - 1 }, () => {
const newHue = (parseInt(hue) + generateRandomNumber(-hueRange, hueRange, random)) % 360;
const newSaturation = Math.max(
0,
Math.min(100, parseInt(saturation) + generateRandomNumber(-saturationRange, saturationRange, random))
);
const newLightness = Math.max(
0,
Math.min(100, parseInt(lightness) + generateRandomNumber(-lightnessRange, lightnessRange, random))
);
return `hsl(${newHue},${newSaturation}%,${newLightness}%)`;
}),
];
}
function hexToRgb(hex) {
const bigint = parseInt(hex.slice(1), 16);
const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
const b = bigint & 255;
return { r, g, b };
}
function rgbToHex(r, g, b) {
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
function calculateColorContrast(color1, color2) {
const rgb1 = hexToRgb(color1);
const rgb2 = hexToRgb(color2);
const lum1 = (0.2126 * rgb1.r + 0.7152 * rgb1.g + 0.0722 * rgb1.b) / 255;
const lum2 = (0.2126 * rgb2.r + 0.7152 * rgb2.g + 0.0722 * rgb2.b) / 255;
const lightest = Math.max(lum1, lum2);
const darkest = Math.min(lum1, lum2);
return (lightest + 0.05) / (darkest + 0.05);
}
function ensureColorContrast(options = {}) {
const { color1, color2, format = 'hex', contrastRatio = 4.5 } = options;
const contrast = calculateColorContrast(color1, color2);
if (contrast >= contrastRatio) {
return [color1, color2];
}
const { r, g, b } = hexToRgb(color1);
const backgroundColor = rgbToHex(r, g, b);
let textColor = color2;
while (calculateColorContrast(backgroundColor, textColor) < contrastRatio) {
const { r, g, b } = hexToRgb(textColor);
textColor = rgbToHex(
Math.min(255, r + 10),
Math.min(255, g + 10),
Math.min(255, b + 10)
);
}
return format === 'hex' ? [backgroundColor, textColor] : [hexToRgb(backgroundColor), hexToRgb(textColor)];
}
// add pastel color
function generateRandomPastelColor(options = {}) {
const { format = 'hex', alpha = false, seed = null } = options;
const random = seed ? mulberry32(seed) : Math.random;
const hue = generateRandomNumber(0, 360, random);
const saturation = generateRandomNumber(25, 50, random);
const lightness = generateRandomNumber(75, 90, random);
const hslColor = `hsl(${hue},${saturation}%,${lightness}%)`;
return format === 'hex' ? hslToHex(hslColor) : (alpha ? hslToRgba(hslColor, random().toFixed(2)) : hslToRgb(hslColor));
}
function generateRandomDarkColor(options = {}) {
const { format = 'hex', alpha = false, seed = null } = options;
const random = seed ? mulberry32(seed) : Math.random;
const hue = generateRandomNumber(0, 360, random);
const saturation = generateRandomNumber(50, 100, random);
const lightness = generateRandomNumber(10, 30, random);
const hslColor = `hsl(${hue},${saturation}%,${lightness}%)`;
return format === 'hex' ? hslToHex(hslColor) : (alpha ? hslToRgba(hslColor, random().toFixed(2)) : hslToRgb(hslColor));
}
function generateRandomLightColor(options = {}) {
const { format = 'hex', alpha = false, seed = null } = options;
const random = seed ? mulberry32(seed) : Math.random;
const hue = generateRandomNumber(0, 360, random);
const saturation = generateRandomNumber(50, 100, random);
const lightness = generateRandomNumber(70, 90, random);
const hslColor = `hsl(${hue},${saturation}%,${lightness}%)`;
return format === 'hex' ? hslToHex(hslColor) : (alpha ? hslToRgba(hslColor, random().toFixed(2)) : hslToRgb(hslColor));
}
function hslToRgb(hslColor) {
const [hue, saturation, lightness] = hslColor.match(/\d+/g);
const h = parseInt(hue) / 360;
const s = parseInt(saturation) / 100;
const l = parseInt(lightness) / 100;
let r, g, b;
if (s === 0) {
r = g = b = l;
} else {
const 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;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return `rgb(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)})`;
}
function hslToRgba(hslColor, alpha) {
const rgbColor = hslToRgb(hslColor);
return rgbColor.replace('rgb', 'rgba').replace(')', `, ${alpha})`);
}
function hslToHex(hslColor) {
const rgbColor = hslToRgb(hslColor);
const [r, g, b] = rgbColor.match(/\d+/g);
return rgbToHex(parseInt(r), parseInt(g), parseInt(b));
}
module.exports = {
generateRandomColor,
generateRandomGradientColors,
generateRandomColorFamily,
ensureColorContrast,
generateRandomPastelColor,
generateRandomDarkColor,
generateRandomLightColor,
};