keeweb/app/scripts/util/data/color.js

134 lines
3.6 KiB
JavaScript
Raw Normal View History

2019-09-15 14:16:32 +02:00
import { Colors } from 'const/colors';
2015-10-17 23:49:24 +02:00
2017-01-31 07:50:28 +01:00
const KnownColors = {};
2015-10-17 23:49:24 +02:00
2020-06-01 16:53:51 +02:00
const Color = function (arg) {
2017-04-27 12:02:41 +02:00
const rgbaMatch = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(,\s*([\d.]+))?\)$/.exec(arg);
if (rgbaMatch) {
this.r = +rgbaMatch[1];
this.g = +rgbaMatch[2];
this.b = +rgbaMatch[2];
this.a = rgbaMatch[4] ? rgbaMatch[4] : 1;
this.setHsl();
} else {
const hexMatch = /^#?([0-9a-f]{3,6})$/i.exec(arg);
if (hexMatch) {
const digits = hexMatch[1];
const len = digits.length === 3 ? 1 : 2;
this.r = parseInt(digits.substr(0, len), 16);
this.g = parseInt(digits.substr(len, len), 16);
this.b = parseInt(digits.substr(len * 2, len), 16);
this.a = 1;
this.setHsl();
} else if (arg instanceof Color) {
this.r = arg.r;
this.g = arg.g;
this.b = arg.b;
this.h = arg.h;
this.s = arg.s;
this.l = arg.l;
this.a = arg.a;
} else {
this.r = this.g = this.b = this.h = this.s = this.l = 0;
this.a = 1;
}
}
2015-10-17 23:49:24 +02:00
};
2020-06-01 16:53:51 +02:00
Color.prototype.setHsl = function () {
2017-01-31 07:50:28 +01:00
const r = this.r / 255;
const g = this.g / 255;
const b = this.b / 255;
2015-10-17 23:49:24 +02:00
2017-01-31 07:50:28 +01:00
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h;
let s;
const l = (max + min) / 2;
2015-10-17 23:49:24 +02:00
if (max === min) {
h = s = 0; // achromatic
} else {
2017-01-31 07:50:28 +01:00
const d = max - min;
2015-10-17 23:49:24 +02:00
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
2019-08-16 23:05:39 +02:00
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;
2015-10-17 23:49:24 +02:00
}
h /= 6;
}
this.h = h;
this.s = s;
this.l = l;
};
2020-06-01 16:53:51 +02:00
Color.prototype.toHex = function () {
2015-10-23 22:11:28 +02:00
return '#' + hex(this.r) + hex(this.g) + hex(this.b);
2015-10-17 23:49:24 +02:00
};
2020-06-01 16:53:51 +02:00
Color.prototype.toRgba = function () {
2017-04-27 12:02:41 +02:00
return `rgba(${Math.round(this.r)},${Math.round(this.g)},${Math.round(this.b)},${this.a})`;
};
2020-06-01 16:53:51 +02:00
Color.prototype.toHsla = function () {
2019-08-18 08:05:38 +02:00
return `hsla(${Math.round(this.h * 100)},${Math.round(this.s * 100)}%,${Math.round(
this.l * 100
)}%,${this.a})`;
2017-04-27 12:02:41 +02:00
};
2020-06-01 16:53:51 +02:00
Color.prototype.distanceTo = function (color) {
2015-10-17 23:49:24 +02:00
return Math.abs(this.h - color.h);
};
2020-06-01 16:53:51 +02:00
Color.prototype.mix = function (another, weight) {
2017-04-27 12:02:41 +02:00
const res = new Color(this);
const anotherWeight = 1 - weight;
res.r = this.r * weight + another.r * anotherWeight;
res.g = this.g * weight + another.g * anotherWeight;
res.b = this.b * weight + another.b * anotherWeight;
res.a = this.a * weight + another.a * anotherWeight;
return res;
};
2020-06-01 16:53:51 +02:00
Color.getNearest = function (colorStr) {
2017-01-31 07:50:28 +01:00
const color = new Color(colorStr);
2015-10-17 23:49:24 +02:00
if (!color.s) {
return null;
}
2017-01-31 07:50:28 +01:00
let selected = null,
minDistance = Number.MAX_VALUE;
2019-09-17 22:17:40 +02:00
for (const [name, col] of Object.entries(KnownColors)) {
2017-01-31 07:50:28 +01:00
const distance = color.distanceTo(col);
2015-10-17 23:49:24 +02:00
if (distance < minDistance) {
minDistance = distance;
selected = name;
}
2019-09-17 22:17:40 +02:00
}
2015-10-17 23:49:24 +02:00
return selected;
};
2020-06-01 16:53:51 +02:00
Color.getKnownBgColor = function (knownColor) {
2015-10-23 22:11:28 +02:00
return Colors.BgColors[knownColor] ? '#' + Colors.BgColors[knownColor] : undefined;
2015-10-17 23:49:24 +02:00
};
2019-09-17 22:17:40 +02:00
for (const [name, val] of Object.entries(Colors.ColorsValues)) {
2015-10-17 23:49:24 +02:00
KnownColors[name] = new Color(val);
2019-09-17 22:17:40 +02:00
}
2015-10-17 23:49:24 +02:00
2017-04-27 12:02:41 +02:00
Color.black = new Color('#000');
2015-10-17 23:49:24 +02:00
function hex(num) {
2017-01-31 07:50:28 +01:00
const str = (num || 0).toString(16);
2015-10-17 23:49:24 +02:00
return str.length < 2 ? '0' + str : str;
}
2019-09-15 14:16:32 +02:00
export { Color };