github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/utils/color.ts (about)

     1  /**
     2   * 判断是否 十六进制颜色值.
     3   * 输入形式可为 #fff000 #f00
     4   *
     5   * @param   String  color   十六进制颜色值
     6   * @return  Boolean
     7   */
     8  export const isHexColor = (color: string) => {
     9    const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6})$/
    10    return reg.test(color)
    11  }
    12  
    13  /**
    14   * RGB 颜色值转换为 十六进制颜色值.
    15   * r, g, 和 b 需要在 [0, 255] 范围内
    16   *
    17   * @return  String          类似#ff00ff
    18   * @param r
    19   * @param g
    20   * @param b
    21   */
    22  export const rgbToHex = (r: number, g: number, b: number) => {
    23    // tslint:disable-next-line:no-bitwise
    24    const hex = ((r << 16) | (g << 8) | b).toString(16)
    25    return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex
    26  }
    27  
    28  /**
    29   * Transform a HEX color to its RGB representation
    30   * @param {string} hex The color to transform
    31   * @returns The RGB representation of the passed color
    32   */
    33  export const hexToRGB = (hex: string, opacity?: number) => {
    34    let sHex = hex.toLowerCase()
    35    if (isHexColor(hex)) {
    36      if (sHex.length === 4) {
    37        let sColorNew = '#'
    38        for (let i = 1; i < 4; i += 1) {
    39          sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1))
    40        }
    41        sHex = sColorNew
    42      }
    43      const sColorChange: number[] = []
    44      for (let i = 1; i < 7; i += 2) {
    45        sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2)))
    46      }
    47      return opacity
    48        ? 'RGBA(' + sColorChange.join(',') + ',' + opacity + ')'
    49        : 'RGB(' + sColorChange.join(',') + ')'
    50    }
    51    return sHex
    52  }
    53  
    54  export const colorIsDark = (color: string) => {
    55    if (!isHexColor(color)) return
    56    const [r, g, b] = hexToRGB(color)
    57      .replace(/(?:\(|\)|rgb|RGB)*/g, '')
    58      .split(',')
    59      .map((item) => Number(item))
    60    return r * 0.299 + g * 0.578 + b * 0.114 < 192
    61  }
    62  
    63  /**
    64   * Darkens a HEX color given the passed percentage
    65   * @param {string} color The color to process
    66   * @param {number} amount The amount to change the color by
    67   * @returns {string} The HEX representation of the processed color
    68   */
    69  export const darken = (color: string, amount: number) => {
    70    color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color
    71    amount = Math.trunc((255 * amount) / 100)
    72    return `#${subtractLight(color.substring(0, 2), amount)}${subtractLight(
    73      color.substring(2, 4),
    74      amount
    75    )}${subtractLight(color.substring(4, 6), amount)}`
    76  }
    77  
    78  /**
    79   * Lightens a 6 char HEX color according to the passed percentage
    80   * @param {string} color The color to change
    81   * @param {number} amount The amount to change the color by
    82   * @returns {string} The processed color represented as HEX
    83   */
    84  export const lighten = (color: string, amount: number) => {
    85    color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color
    86    amount = Math.trunc((255 * amount) / 100)
    87    return `#${addLight(color.substring(0, 2), amount)}${addLight(
    88      color.substring(2, 4),
    89      amount
    90    )}${addLight(color.substring(4, 6), amount)}`
    91  }
    92  
    93  /* Suma el porcentaje indicado a un color (RR, GG o BB) hexadecimal para aclararlo */
    94  /**
    95   * Sums the passed percentage to the R, G or B of a HEX color
    96   * @param {string} color The color to change
    97   * @param {number} amount The amount to change the color by
    98   * @returns {string} The processed part of the color
    99   */
   100  const addLight = (color: string, amount: number) => {
   101    const cc = parseInt(color, 16) + amount
   102    const c = cc > 255 ? 255 : cc
   103    return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`
   104  }
   105  
   106  /**
   107   * Calculates luminance of an rgb color
   108   * @param {number} r red
   109   * @param {number} g green
   110   * @param {number} b blue
   111   */
   112  const luminanace = (r: number, g: number, b: number) => {
   113    const a = [r, g, b].map((v) => {
   114      v /= 255
   115      return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4)
   116    })
   117    return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722
   118  }
   119  
   120  /**
   121   * Calculates contrast between two rgb colors
   122   * @param {string} rgb1 rgb color 1
   123   * @param {string} rgb2 rgb color 2
   124   */
   125  const contrast = (rgb1: string[], rgb2: number[]) => {
   126    return (
   127      (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) /
   128      (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05)
   129    )
   130  }
   131  
   132  /**
   133   * Determines what the best text color is (black or white) based con the contrast with the background
   134   * @param hexColor - Last selected color by the user
   135   */
   136  export const calculateBestTextColor = (hexColor: string) => {
   137    const rgbColor = hexToRGB(hexColor.substring(1))
   138    const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0])
   139  
   140    return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF'
   141  }
   142  
   143  /**
   144   * Subtracts the indicated percentage to the R, G or B of a HEX color
   145   * @param {string} color The color to change
   146   * @param {number} amount The amount to change the color by
   147   * @returns {string} The processed part of the color
   148   */
   149  const subtractLight = (color: string, amount: number) => {
   150    const cc = parseInt(color, 16) - amount
   151    const c = cc < 0 ? 0 : cc
   152    return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`
   153  }