一、3、4位数字表示的16进制颜色转换成6位
3位转6位
3位数的 每一个数字表示6位数中的两位, 这个补全比较简单,直接举例子:
- #fff => #ffffff
- #123 => #112233
- #a2e => #aa22ee
4位转6位
4位数的前三位和3转6一样,每一个数字表示6位数中的两位,多的第四位表示的是透明度
- #ffff => #ffffff + 透明度 1 (F/16)
- #1234 => #112233 + 透明度 0.25 (4/16)
- #a2e8 => #aa22ee + 透明度 0.5 (8/16)
二、 生成颜色相近的渐变色:
通常我们给用户diy的颜色,如果是纯色的话效果不怎么好,需要向深一点或者浅一点进行线性渐变;
export function getColor(color, amount) {
// 是#开头的十六进制的色值
if (/^#[0-9A-Fa-f]?/.test(color)) {
// 如果是4位数的色值,补全成6位,并且取出透明度值,要不计算num会有问题
const fourReg = /^#[0-9A-Fa-f]{4}$/;
let alpa = 0;
if (fourReg.test(color)) {
const fourLengthReg = /^#([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f])/;
const colorCopy = color;
color = color.replace(fourLengthReg, `#$1$1$2$2$3$3`);
alpa = colorCopy.replace(fourLengthReg, `$4`);
}
// 如果是3位数的色值,补全成6位,
const threeReg = /^#[0-9A-Fa-f]{3}$/;
if (threeReg.test(color)) {
const testReg = /^#([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f])/;
color = color.replace(testReg, `#$1$1$2$2$3$3`);
}
const fill = str => ('00' + str).slice(-2);
const rgb = getRgb(color.substr(1), amount);
const newColor =
'#' + fill(rgb.red.toString(16)) + fill(rgb.green.toString(16)) + fill(rgb.blue.toString(16));
// 如果颜色有透明度,则生成的渐变色也加上一样的透明度
if (alpa) {
return set16ToRgb(newColor, alpa / 16);
}
return newColor;
// 如果色值是 rgba 形式的
} else if (/rgba\(/.test(color)) {
return getColor16(color.replace(/;/, ''), amount);
}
}
// rgba 格式的色值,取渐变色
export function getColor16(rgba, amount) {
const deleteRegular = /((^rgba\()|(\)))/gi;
// 去除开头的 'rgba(' 和后面的 ')'
const newColor = rgba.replace(deleteRegular, '');
const rgbaList = newColor.split(',');
const alpa = Number(rgbaList[3]);
const fill = str => ('00' + str).slice(-2);
const color16 = `${fill(Number(rgbaList[0]).toString(16))}${fill(
Number(rgbaList[1]).toString(16)
)}${fill(Number(rgbaList[2]).toString(16))}`;
const rgb = getRgb(color16, amount);
const resolveColor =
'#' + fill(rgb.red.toString(16)) + fill(rgb.green.toString(16)) + fill(rgb.blue.toString(16));
if (alpa) {
const returnColor = set16ToRgb(resolveColor, alpa);
return returnColor;
} else {
const returnColor = set16ToRgb(resolveColor, '0.1');
return returnColor;
}
}
function getRgb(color, amount) {
const clamp = val => Math.min(Math.max(val, 0), 0xff);
const num = parseInt(color, 16);
// 用>>不用考虑小于零 或者大于 ffffff 的情况
const red = clamp((num >> 16) + amount);
const green = clamp(((num >> 8) & 0x00ff) + amount);
const blue = clamp((num & 0x0000ff) + amount);
return {
red,
green,
blue
};
}
// 给十六进制颜色加上透明度,转换成rgba
export function set16ToRgb(str, alpha) {
const reg = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;
if (reg.test(str)) {
let newStr = str.toLowerCase().replace(/#/g, '');
const len = newStr.length;
if (len === 3) {
let t = '';
for (let i = 0; i < len; i++) {
t += newStr.slice(i, i + 1).concat(newStr.slice(i, i + 1));
}
newStr = t;
}
const arr = [];
for (let i = 0; i < 6; i = i + 2) {
const s = newStr.slice(i, i + 2);
arr.push(parseInt('0x' + s));
}
return `rgba(${arr[0]},${arr[1]},${arr[2]},${alpha || '0'})`;
}
const rgbaReg = /^(rgba\()(\d+,?){3}/;
if (rgbaReg.test(str)) {
const deleteRegular = /((^rgba\()|(\)))/gi;
const newColor = str.replace(deleteRegular, '');
const arr = newColor.split(',');
const alpa = Number(arr[3]);
return `rgba(${arr[0]},${arr[1]},${arr[2]},${(alpa * alpha).toFixed(3)})`;
}
}
// 是否浅色
export function isLight(rgb = [152, 152, 152]) {
return 0.213 * rgb[0] + 0.715 * rgb[1] + 0.072 * rgb[2] > 255 / 2;
}
// 校验颜色是否为浅色
export function checkIsLightColor(color) {
let rgbaColor = getColor(color, 0);
const reg = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;
if (reg.test(rgbaColor)) {
rgbaColor = set16ToRgb(rgbaColor, 1);
}
const deleteRegular = /((^rgba\()|(\)))/gi;
// 去除开头的 'rgba(' 和后面的 ')'
const newColor = rgbaColor.replace(deleteRegular, '');
console.log('newColor newColor', newColor);
const rgbaList = newColor.split(',');
return isLight(rgbaList.splice(0, 3));
}
export function colorCheck(value) {
if (!value) return false;
// 正则匹配输入的内容是否是带#开头后面,3|4|6个十六进制字符的颜色(0~f)
const regular = /^#(([0-9A-Fa-f]{3}){1,2}|[0-9A-Fa-f]{4})$/;
const rgbaRegular = /rgba\(/;
return regular.test(value) || rgbaRegular.test(value);
}
三、 识别一个色值|图片是深色还是浅色:
因为RGB三种颜色对人眼的刺激程度不同,所以分别对RGB添加不同的权重。得出的平均值来判断色值是深色还是浅色,坚于红光有较长的波长,而绿光波长较短对视觉的刺激相对较小,(红光:625740nm,绿光:波长范围:492~577nm,蓝光:波长范围:440475nm)所以我们要有意的减小红光的权重而提升绿光的权重。
// 色值是否为浅色
export function isLight(rgb = [152, 152, 152]) {
return 0.213 * rgb[0] + 0.715 * rgb[1] + 0.072 * rgb[2] > 255 / 2;
}