Javascript 如何根据当前颜色生成相反的颜色?
我正在尝试创建一种与当前颜色相反的颜色。我的意思是,如果当前颜色是黑色,那么我需要生成白色 实际上我有一个文本(这个文本的颜色是动态的,它的颜色可以随意设置)。该文本被放入Javascript 如何根据当前颜色生成相反的颜色?,javascript,jquery,html,css,colors,Javascript,Jquery,Html,Css,Colors,我正在尝试创建一种与当前颜色相反的颜色。我的意思是,如果当前颜色是黑色,那么我需要生成白色 实际上我有一个文本(这个文本的颜色是动态的,它的颜色可以随意设置)。该文本被放入div中,我需要为div的背景色设置该文本的相反颜色。我希望div(颜色透视图)中的文本清晰 相反的颜色表示:暗/亮 我有文本的当前颜色,我可以将其传递给此函数: var TextColor = #F0F0F0; // for example (it is a bright color) function create
div
中,我需要为div的背景色设置该文本的相反颜色。我希望div
(颜色透视图)中的文本清晰
相反的颜色表示:暗/亮
我有文本的当前颜色,我可以将其传递给此函数:
var TextColor = #F0F0F0; // for example (it is a bright color)
function create_opp_color(current color) {
// create opposite color according to current color
}
create_opp_color(TextColor); // this should be something like "#202020" (or a dark color)
有没有办法创建create\u opp\u color()
函数?注意可访问性(AA/AAA)。颜色对比本身是无用的。对于色盲的人来说,不同的颜色完全没有对比。
我想这种颜色的计算可以是这样的:
(为了简单起见,请使用“HLS”)
- 将色调旋转180º以获得(可能无用的)最大颜色对比度
- 计算亮度差
- (计算色差…不必要,它是最大的或几乎)
- 计算对比度
- 如果生成的颜色符合要求,则计算结束,如果不符合,则循环:
- 如果亮度差不够,则增加或
将计算出的颜色亮度(L)减少一定量或比率(向上或向下)
取决于原始颜色亮度:>或
- 检查它是否符合您的要求,如果符合,计算结束
- 如果亮度可以增加(或减少),没有符合要求的有效颜色,只需尝试黑色和白色,选择其中的“最佳颜色”(可能是对比度较大的颜色)并结束
根据我对你问题的理解,你所说的反色是指反色
InvertedColorComponent = 0xFF - ColorComponent
所以对于红色(#FF0000)这意味着:
R=0xFF或255
G=0x00或0
B=0x00或0
倒红色(#00FFFF)为:
另一个例子:
黑色(#000000)变成白色(#FFFFFF)
橙色(#FFA500)变为#005AFF更新:生产就绪代码开启。
我会这样做:
将十六进制转换为RGB
反转R、G和B分量
将每个组件转换回十六进制
用零填充每个组件并输出
函数反转颜色(十六进制){
if(十六进制索引of('#')==0){
十六进制=十六进制切片(1);
}
//将3位十六进制转换为6位。
如果(十六进制长度===3){
十六进制=十六进制[0]+十六进制[0]+十六进制[1]+十六进制[1]+十六进制[2]+十六进制[2];
}
如果(十六进制长度!==6){
抛出新错误(“十六进制颜色无效”);
}
//反转颜色分量
var r=(255-parseInt(十六进制切片(0,2,16)).toString(16),
g=(255-parseInt(十六进制切片(2,4,16)).toString(16),
b=(255-parseInt(十六进制切片(4,6,16)).toString(16);
//用零填充每个字符并返回
返回“#”+padZero(r)+padZero(g)+padZero(b);
}
函数padZero(str,len){
len=len | | 2;
var zeros=新数组(len).join('0');
返回(零+str).slice(-len);
}
示例输出:
高级版本:
这有一个bw
选项,将决定是反转为黑色还是白色;因此,你会得到更多的对比度,这通常对人眼更有利
函数反转颜色(十六进制,bw){
if(十六进制索引of('#')==0){
十六进制=十六进制切片(1);
}
//将3位十六进制转换为6位。
如果(十六进制长度===3){
十六进制=十六进制[0]+十六进制[0]+十六进制[1]+十六进制[1]+十六进制[2]+十六进制[2];
}
如果(十六进制长度!==6){
抛出新错误(“十六进制颜色无效”);
}
var r=parseInt(十六进制切片(0,2,16),
g=parseInt(十六进制切片(2,4,16),
b=parseInt(十六进制切片(4,6,16));
如果(bw){
// http://stackoverflow.com/a/3943023/112731
回报率(r*0.299+g*0.587+b*0.114)>186
? '#000000'
:“#FFFFFF”;
}
//反转颜色分量
r=(255-r).toString(16);
g=(255-g).toString(16);
b=(255-b).toString(16);
//用零填充每个字符并返回
返回“#”+padZero(r)+padZero(g)+padZero(b);
}
示例输出:
简单地将背景颜色翻转为文本颜色对于某些中等范围的值不起作用,例如0x808080
。我尝试过改变颜色值-(v+0x80)%0x100
。看一个演示
同意来自的评论-尽管希望看到每个计算步骤的更详细算法 使用CSS实现此目的的简单方法:
mix-blend-mode: difference;
color:white;
用于反转元素颜色的函数。获取每个文本的亮度,如果它们接近,则反转文本颜色
function adjustColor(element) {
var style = window.getComputedStyle(element);
var background = new Color(style['background-color']);
var text = new Color(style['color']);
if (Math.abs(background.luma - text.luma) < 100) {
element.style.color = text.inverted.toString();
}
}
功能调整颜色(元件){
var style=window.getComputedStyle(元素);
var background=新颜色(样式['background-Color']);
var text=新颜色(样式['Color']);
if(Math.abs(background.luma-text.luma)<100){
element.style.color=text.inversed.toString();
}
}
下面是颜色“类”。接受十六进制、rgb、rgba(即使有百分比),也可以输出到任意一个。Explorer将需要和的多边形填充,而toString()方法中的插值字符串将需要使用concat进行修改
const Color = (function () {
function toHex(num, padding) { return num.toString(16).padStart(padding || 2); }
function parsePart(value) {
var perc = value.lastIndexOf('%');
return perc < 0 ? value : value.substr(0, perc);
}
function Color(data) {
if (arguments.length > 1) {
this[0] = arguments[0];
this[1] = arguments[1];
this[2] = arguments[2];
if (arguments.length > 3) { this[3] = arguments[3]; }
} else if (data instanceof Color || Array.isArray(data)) {
this[0] = data[0];
this[1] = data[1];
this[2] = data[2];
this[3] = data[3];
} else if (typeof data === 'string') {
data = data.trim();
if (data[0] === "#") {
switch (data.length) {
case 4:
this[0] = parseInt(data[1], 16); this[0] = (this[0] << 4) | this[0];
this[1] = parseInt(data[2], 16); this[1] = (this[1] << 4) | this[1];
this[2] = parseInt(data[3], 16); this[2] = (this[2] << 4) | this[2];
break;
case 9:
this[3] = parseInt(data.substr(7, 2), 16);
//Fall Through
case 7:
this[0] = parseInt(data.substr(1, 2), 16);
this[1] = parseInt(data.substr(3, 2), 16);
this[2] = parseInt(data.substr(5, 2), 16);
break;
}
} else if (data.startsWith("rgb")) {
var parts = data.substr(data[3] === "a" ? 5 : 4, data.length - (data[3] === "a" ? 6 : 5)).split(',');
this.r = parsePart(parts[0]);
this.g = parsePart(parts[1]);
this.b = parsePart(parts[2]);
if (parts.length > 3) { this.a = parsePart(parts[3]); }
}
}
}
Color.prototype = {
constructor: Color,
0: 255,
1: 255,
2: 255,
3: 255,
get r() { return this[0]; },
set r(value) { this[0] = value == null ? 0 : Math.max(Math.min(parseInt(value), 255), 0); },
get g() { return this[1]; },
set g(value) { this[1] = value == null ? 0 : Math.max(Math.min(parseInt(value), 255), 0); },
get b() { return this[2]; },
set b(value) { this[2] = value == null ? 0 : Math.max(Math.min(parseInt(value), 255), 0); },
get a() { return this[3] / 255; },
set a(value) { this[3] = value == null ? 255 : Math.max(Math.min(value > 1 ? value : parseFloat(value) * 255, 255), 0); },
get luma() { return .299 * this.r + .587 * this.g + .114 * this.b; },
get inverted() { return new Color(255 - this[0], 255 - this[1], 255 - this[2], this[3]); },
toString: function (option) {
if (option === 16) {
return '#' + toHex(this.r) + toHex(this.g) + toHex(this.b) + (this[3] === 255 ? '' : toHex(this[3]));
} else if (option === '%') {
if (this.a !== 1) {
return `rgba(${this.r / 255 * 100}%, ${this.b / 255 * 100}%, ${this.g / 255 * 100}%, ${this.a / 255})`;
} else {
return `rgb(${this.r / 255 * 100}%, ${this.b / 255 * 100}%, ${this.g / 255 * 100})%`;
}
} else {
if (this.a !== 1) {
return `rgba(${this.r}, ${this.b}, ${this.g}, ${this.a})`;
} else {
return `rgb(${this.r}, ${this.b}, ${this.g})`;
}
}
}
};
return Color;
}());
const Color=(函数(){
函数toHex(num,padding){return num.toString(16).padStart(padding | | 2)}
函数解析部分(值){
var perc=value.lastIndexOf('%');
返回perc<0?值:value.substr(0,perc);
}
功能颜色(数据){
如果(arguments.length>1){
此[0]=参数[0];
此[1]=参数[1];
此[2]=参数[2];
如果(arguments.length>3){this[3]=arguments[3];}
}否则,如果(数据仪表)
const Color = (function () {
function toHex(num, padding) { return num.toString(16).padStart(padding || 2); }
function parsePart(value) {
var perc = value.lastIndexOf('%');
return perc < 0 ? value : value.substr(0, perc);
}
function Color(data) {
if (arguments.length > 1) {
this[0] = arguments[0];
this[1] = arguments[1];
this[2] = arguments[2];
if (arguments.length > 3) { this[3] = arguments[3]; }
} else if (data instanceof Color || Array.isArray(data)) {
this[0] = data[0];
this[1] = data[1];
this[2] = data[2];
this[3] = data[3];
} else if (typeof data === 'string') {
data = data.trim();
if (data[0] === "#") {
switch (data.length) {
case 4:
this[0] = parseInt(data[1], 16); this[0] = (this[0] << 4) | this[0];
this[1] = parseInt(data[2], 16); this[1] = (this[1] << 4) | this[1];
this[2] = parseInt(data[3], 16); this[2] = (this[2] << 4) | this[2];
break;
case 9:
this[3] = parseInt(data.substr(7, 2), 16);
//Fall Through
case 7:
this[0] = parseInt(data.substr(1, 2), 16);
this[1] = parseInt(data.substr(3, 2), 16);
this[2] = parseInt(data.substr(5, 2), 16);
break;
}
} else if (data.startsWith("rgb")) {
var parts = data.substr(data[3] === "a" ? 5 : 4, data.length - (data[3] === "a" ? 6 : 5)).split(',');
this.r = parsePart(parts[0]);
this.g = parsePart(parts[1]);
this.b = parsePart(parts[2]);
if (parts.length > 3) { this.a = parsePart(parts[3]); }
}
}
}
Color.prototype = {
constructor: Color,
0: 255,
1: 255,
2: 255,
3: 255,
get r() { return this[0]; },
set r(value) { this[0] = value == null ? 0 : Math.max(Math.min(parseInt(value), 255), 0); },
get g() { return this[1]; },
set g(value) { this[1] = value == null ? 0 : Math.max(Math.min(parseInt(value), 255), 0); },
get b() { return this[2]; },
set b(value) { this[2] = value == null ? 0 : Math.max(Math.min(parseInt(value), 255), 0); },
get a() { return this[3] / 255; },
set a(value) { this[3] = value == null ? 255 : Math.max(Math.min(value > 1 ? value : parseFloat(value) * 255, 255), 0); },
get luma() { return .299 * this.r + .587 * this.g + .114 * this.b; },
get inverted() { return new Color(255 - this[0], 255 - this[1], 255 - this[2], this[3]); },
toString: function (option) {
if (option === 16) {
return '#' + toHex(this.r) + toHex(this.g) + toHex(this.b) + (this[3] === 255 ? '' : toHex(this[3]));
} else if (option === '%') {
if (this.a !== 1) {
return `rgba(${this.r / 255 * 100}%, ${this.b / 255 * 100}%, ${this.g / 255 * 100}%, ${this.a / 255})`;
} else {
return `rgb(${this.r / 255 * 100}%, ${this.b / 255 * 100}%, ${this.g / 255 * 100})%`;
}
} else {
if (this.a !== 1) {
return `rgba(${this.r}, ${this.b}, ${this.g}, ${this.a})`;
} else {
return `rgb(${this.r}, ${this.b}, ${this.g})`;
}
}
}
};
return Color;
}());
function invertHex(hex) {
return (Number(`0x1${hex}`) ^ 0xFFFFFF).toString(16).substr(1).toUpperCase()
}
invertHex('00FF00'); // Returns FF00FF
const invertColor = (col) => {
const colors = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
let inverseColor = '#'
col.replace('#','').split('').forEach(i => {
const index = colors.indexOf(i)
inverseColor += colors.reverse()[index]
})
return inverseColor
}
invertHex(hex: string) {
if (hex.indexOf('#') === 0) {
hex = hex.slice(1);
}
if (hex.length != 6) {
console.warn('Hex color must be six hex numbers in length.');
return '#' + hex;
}
hex = hex.toUpperCase();
const splitNum = hex.split('');
let resultNum = '';
const simpleNum = 'FEDCBA9876'.split('');
const complexNum = {
A: '5', B: '4', C: '3', D: '2', E: '1', F: '0'
};
for (let i = 0; i < 6; i++) {
if (!isNaN(Number(splitNum[i]))) {
resultNum += simpleNum[splitNum[i]];
} else if (complexNum[splitNum[i]]) {
resultNum += complexNum[splitNum[i]];
} else {
console.warn('Hex colors must only include hex numbers 0-9, and A-F');
return '#' + hex;
}
}
return '#' + resultNum;
}
function invertColor(color) {
return '#' + ("000000" + (0xFFFFFF ^ parseInt(color.substring(1),16)).toString(16)).slice(-6);
}
def hex_to_rgb(value):
value = value.lstrip('#')
lv = len(value)
return tuple(int(value[i:i + lv // 3], 16) for i in range(0, lv, lv // 3))
def invertColor(color, bw=False):
# strip the # from the beginning
color = color.lstrip('#')
# convert the string into hex
color = int(color, 16)
# invert the three bytes
# as good as substracting each of RGB component by 255(FF)
comp_color = 0xFFFFFF ^ color
# convert the color back to hex by prefixing a #
comp_color = "#%06X" % comp_color
rgb_color = hex_to_rgb(comp_color)
if (bw):
# http://stackoverflow.com/a/3943023/112731
bw_value = rgb_color[0]*0.299 + rgb_color[0]*0.587 + rgb_color[0]*0.114
if (bw_value>186):
comp_color = "#FFFFFF"
else:
comp_color = "#000000"
# return the result
return comp_color
color = "#fffff1"
print invertColor(color, bw=True)