js/ts颜色格式转换

js/ts颜色格式转换

目前主流浏览器支持度的颜色为关键字 / HEX / RGB / HSL, 新的色彩函数HWB/LAB/LCH支持度并不高, 因此不在本文讨论范围内

效果如下:

image-20230828093745503

色彩语法简介:

  1. 关键字

    颜色关键字: 如red / black

    transparent 关键字: 表示透明

    currentColor 关键字: 表示继承自上级的颜色

  2. HEX / HEXA 十六进制符号

    使用RGB的16进制表示, 完整表示为#RRGGBB[AA], 其中AA表示透明度, 范围0-255(00-FF), 默认为FF

    另一种表示方式为#RGB[A], 可选值为(0-F), 为上述的缩写版, 如#F09表示#FF0099

  3. RGB / RGBA函数

    语法: rgb[a](R, G, B[, A])或者rgb[a](R G B / A), 即逗号表示法和空格表示法

  4. HSL / HSLA函数

    与HEX / RGB不同, 它们被称为RGB颜色, 即RED-GREEN-BLUE-ALPHA(红绿蓝-透明度)

    HSL则表示色相 - 饱和度 - 亮度(Hue-saturation-lightness), 在可视化调整界面, HSL将比RGB更直观

    语法: hsl[a](H, S, L[, A])或者hsl[a](H S L / A), 即逗号表示法和空格表示法

    其中H没有单位时, 表示度数(0-360), 如0deg和360deg表示红色, 绿色为120, 蓝色为240, 并且支持负数, 如 -120deg=240deg, 480deg=120deg, -1turn = 1turn等

    S(饱和度)和L(亮度)与A(透明度)则使用百分比 / 小数表示

  5. 此外以上介绍仅仅是一个简介, 具体详细规则可参考MDN

代码奉上:

这里使用了一个小技巧, 颜色关键字 / hex / hsl / rgb为了保持代码简洁易懂, 使用浏览器来辅助解析, 虽然会有稍微的一点性能损耗, 但是却大幅降低了代码量

export class LyColor {
  // red
  private readonly r: number
  // green
  private readonly g: number
  // blue
  private readonly b: number
  // alpha
  private readonly a: number

  constructor(color: string) {
    const div = document.createElement('div')
    document.body.appendChild(div)
    div.style.color = color
    const computedColor = window.getComputedStyle(div).color
    document.body.removeChild(div)
    const [r = 0, g = 0, b = 0, a = 255] = computedColor.match(/(\d+%?)/g) ?? []
    this.r = +r
    this.g = +g
    this.b = +b
    this.a = +a
  }

  toHex() {
    return `#${LyColor.#hex(this.r)}${LyColor.#hex(this.g)}${LyColor.#hex(this.b)}`
  }

  toHexA() {
    return `#${LyColor.#hex(this.r)}${LyColor.#hex(this.g)}${LyColor.#hex(this.b)}${LyColor.#hex(this.a)}`
  }

  toRGB() {
    return `rgb(${this.r} ${this.g} ${this.b})`
  }

  toRGBA() {
    return `rgba(${this.r} ${this.g} ${this.b} / ${this.a})`
  }

  toHSL() {
    const [h, s, l] = this.getHSLA()
    return `hsl(${h} ${s}% ${l}%)`
  }

  toHSLA() {
    const [h, s, l, a] = this.getHSLA()
    return `hsla(${h} ${s}% ${l}% / ${a})`
  }

  getHSLA(): [h: number, s: number, l: number, a: number] {
    const r = this.r / 255, g = this.g / 255, b = this.b / 255
    let minC = Math.min(r, g, b), maxC = Math.max(r, g, b), delta = maxC - minC
    let h: number, s: number, l: number
    if (delta === 0) {
      h = 0
    } else if (maxC == r) {
      h = ((g - b) / delta) % 6
    } else if (maxC == g) {
      h = (b - r) / delta + 2
    } else {
      h = (r - g) / delta + 4
    }
    h = Math.round(h * 60)

    if (h < 0)
      h += 360

    l = (maxC + minC) / 2

    s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1))

    s = +(s * 100).toFixed(1)
    l = +(l * 100).toFixed(1)
    return [h, s, l, this.a]
  }

  getRGBA(): [r: number, g: number, b: number, a: number] {
    return [this.r, this.g, this.b, this.a]
  }

  static #hex(decimal: number) {
    const hex = decimal.toString(16)
    return hex.length === 1 ? '0' + hex : hex
  }
}

使用方式:

new LyColor('rgb(1, 2, 3)').toHex() // #010203

demo见github

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值