Bilibili-Evolved/client/color-processor.js
2019-03-19 15:31:42 +08:00

173 lines
4.1 KiB
JavaScript

export class ColorProcessor
{
constructor(hex)
{
this.hex = hex;
}
get rgb()
{
return this.hexToRgb(this.hex);
}
get rgba()
{
return this.hexToRgba(this.hex);
}
getHexRegex(alpha, shorthand)
{
const repeat = shorthand ? "" : "{2}";
const part = `([a-f\\d]${repeat})`;
const count = alpha ? 4 : 3;
const pattern = `#?${part.repeat(count)}`;
return new RegExp(pattern, "ig");
}
hexToRgbOrRgba(hex, alpha)
{
const isShortHand = hex.length < 6;
if (isShortHand)
{
const shorthandRegex = this.getHexRegex(alpha, true);
hex = hex.replace(shorthandRegex, function (...args)
{
let result = "";
let i = 1;
while (args[i])
{
result += args[i].repeat(2);
i++;
}
return result;
});
}
const regex = this.getHexRegex(alpha, false);
const regexResult = regex.exec(hex);
if (regexResult)
{
const color = {
r: parseInt(regexResult[1], 16),
g: parseInt(regexResult[2], 16),
b: parseInt(regexResult[3], 16),
};
if (regexResult[4])
{
color.a = parseInt(regexResult[4], 16) / 255;
}
return color;
}
else if (alpha)
{
const rgb = this.hexToRgbOrRgba(hex, false);
if (rgb)
{
rgb.a = 1;
return rgb;
}
}
return null;
}
hexToRgb(hex)
{
return this.hexToRgbOrRgba(hex, false);
}
hexToRgba(hex)
{
return this.hexToRgbOrRgba(hex, true);
}
rgbToString(color)
{
if (color.a)
{
return `rgba(${color.r},${color.g},${color.b},${color.a})`;
}
return `rgb(${color.r},${color.g},${color.b})`;
}
rgbToHsb(rgb)
{
const { r, g, b, } = rgb;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const delta = max - min;
const s = Math.round((max === 0 ? 0 : delta / max) * 100);
const v = Math.round(max / 255 * 100);
let h;
if (delta === 0)
{
h = 0;
}
else if (r === max)
{
h = (g - b) / delta % 6;
}
else if (g === max)
{
h = (b - r) / delta + 2;
}
else if (b === max)
{
h = (r - g) / delta + 4;
}
h = Math.round(h * 60);
if (h < 0)
{
h += 360;
}
return { h: h, s: s, b: v, };
}
get hsb()
{
return this.rgbToHsb(this.rgb);
}
get grey()
{
const color = this.rgb;
return 1 - (0.299 * color.r + 0.587 * color.g + 0.114 * color.b) / 255;
}
get foreground()
{
const color = this.rgb;
if (color && this.grey < 0.35)
{
return "#000";
}
return "#fff";
}
makeImageFilter(originalRgb)
{
const { h, s, } = this.rgbToHsb(originalRgb);
const targetColor = this.hsb;
const hue = targetColor.h - h;
const saturate = ((targetColor.s - s) / 100 + 1) * 100;
// const brightness = ((targetColor.b - b) / 100 + 1) * 100;
const filter = `hue-rotate(${hue}deg) saturate(${saturate}%)`;
return filter;
}
get blueImageFilter()
{
const blueColor = {
r: 0,
g: 160,
b: 213,
};
return this.makeImageFilter(blueColor);
}
get pinkImageFilter()
{
const pinkColor = {
r: 251,
g: 113,
b: 152,
};
return this.makeImageFilter(pinkColor);
}
get brightness()
{
return `${this.foreground === "#000" ? "100" : "0"}%`;
}
get filterInvert()
{
return this.foreground === "#000" ? "invert(0)" : "invert(1)";
}
}