mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
138 lines
3.3 KiB
JavaScript
138 lines
3.3 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)'
|
|
}
|
|
}
|