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 }