Bilibili-Evolved/src/client/color-processor.js
2020-03-02 22:18:35 +08:00

145 lines
3.5 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
const mode = settings.foregroundColorMode
if (mode === '自动' || mode === undefined) {
if (color && this.grey < 0.35) {
return '#000'
}
return '#fff'
} else if (mode === '黑色') {
return '#000'
} else if (mode === '白色') {
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)'
}
}