如何根据当前颜色生成相反的颜色?

时间:2016-03-13 11:27:28

标签: javascript jquery html css colors

我试图创建与当前颜色相反的颜色。我的意思是如果当前颜色是黑色,那么我需要生成白色

实际上我有一个文本(这个文本的颜色是动态的,它的颜色可以随机制作)。该文字属于div,我需要为background-color的{​​{1}}设置该文字的相反颜色。我希望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) 函数吗?

14 个答案:

答案 0 :(得分:112)

更新GitHub上的生产就绪代码。

我就是这样做的:

  1. 将HEX转换为RGB
  2. 反转R,G和B组件
  3. 将每个组件转换回HEX
  4. 用零填充每个组件并输出。
  5. function invertColor(hex) {
        if (hex.indexOf('#') === 0) {
            hex = hex.slice(1);
        }
        // convert 3-digit hex to 6-digits.
        if (hex.length === 3) {
            hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
        }
        if (hex.length !== 6) {
            throw new Error('Invalid HEX color.');
        }
        // invert color components
        var r = (255 - parseInt(hex.slice(0, 2), 16)).toString(16),
            g = (255 - parseInt(hex.slice(2, 4), 16)).toString(16),
            b = (255 - parseInt(hex.slice(4, 6), 16)).toString(16);
        // pad each with zeros and return
        return '#' + padZero(r) + padZero(g) + padZero(b);
    }
    
    function padZero(str, len) {
        len = len || 2;
        var zeros = new Array(len).join('0');
        return (zeros + str).slice(-len);
    }
    

    示例输出:

    enter image description here

    高级版:

    这有一个bw选项,用于决定是否反转为黑色或白色;所以你会得到更多的对比度,这对人眼来说通常更好。

    function invertColor(hex, bw) {
        if (hex.indexOf('#') === 0) {
            hex = hex.slice(1);
        }
        // convert 3-digit hex to 6-digits.
        if (hex.length === 3) {
            hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
        }
        if (hex.length !== 6) {
            throw new Error('Invalid HEX color.');
        }
        var r = parseInt(hex.slice(0, 2), 16),
            g = parseInt(hex.slice(2, 4), 16),
            b = parseInt(hex.slice(4, 6), 16);
        if (bw) {
            // http://stackoverflow.com/a/3943023/112731
            return (r * 0.299 + g * 0.587 + b * 0.114) > 186
                ? '#000000'
                : '#FFFFFF';
        }
        // invert color components
        r = (255 - r).toString(16);
        g = (255 - g).toString(16);
        b = (255 - b).toString(16);
        // pad each with zeros and return
        return "#" + padZero(r) + padZero(g) + padZero(b);
    }
    

    示例输出:

    enter image description here

答案 1 :(得分:11)

@Onur的answer bw部分的纯CSS实现。

  <input type="color" oninput="['--r','--g','--b'].forEach((k,i)=>this.nextElementSibling.style.setProperty(k,parseInt(event.target.value.slice(1+i*2,3+i*2),16)))" />
 
  <div style="--r: 0; --g: 0; --b: 0; --c: calc(-1 * ((var(--r) * 0.299 + var(--g) * 0.587 + var(--b) * 0.114) - 186) * 255)">
    <div style="background-color: rgb(var(--r), var(--g), var(--b)); color: rgb(var(--c), var(--c), var(--c))">Test</div>
  </div>

答案 2 :(得分:7)

使用CSS实现此目的的简单方法:

mix-blend-mode: difference;
color:white;

答案 3 :(得分:4)

注意可行性(AA / AAA)。颜色对比本身是无用的。对于色盲人来说,真正不同的颜色根本没有对比。 恕我直言,这种颜色的计算可能是这样的:

(为简单起见,请使用“HLS”)

  • 旋转色调180º以获得(可能无用的)最大色彩对比度
  • 计算亮度差异。
  • (计算色差......不必要,最大或几乎)
  • 计算对比度。
  • 如果生成的颜色符合要求计算结束,如果不符合,则循环:
    • 如果亮度差异没有增加或 将计算出的颜色光度(L)减少一定量或比例(向上或向下) 根据原始颜色亮度下降:&gt;或者&lt;比中旬 值)
    • 如果计算结束,请检查它是否符合您的要求。
    • 如果光度可以增加(或减少),则没有有效的颜色可以满足要求,只需尝试黑白,取其中的“最佳”(可能是对比度较大的那种)并结束。

答案 4 :(得分:4)

在我对你的问题的理解中,你用相反的颜色来表示反色。

InvertedColorComponent = 0xFF - ColorComponent

因此,对于红色(#FF0000),这意味着:     R = 0xFF或255     G = 0x00或0     B = 0x00或0

倒红色(#00FFFF)是:

R = 0xFF - 0xFF = 0x00 or 255 - 255 = 0
G = 0xFF - 0x00 = 0xFF or 255 - 0 = 255
B = 0xFF - 0x00 = 0xFF or 255 - 0 = 255

另一个例子:

黑色(#000000)变为白色(#FFFFFF)。

橙色(#FFA500)变为#005AFF

答案 5 :(得分:2)

简单地将背景颜色翻转为文字颜色不会使用某些中间范围值,例如0x808080。我尝试过改变颜色值 - (v + 0x80) % 0x100。查看演示here

同意miguel-svq的评论 - 尽管希望每个计算步骤都能看到更详细的算法。

答案 6 :(得分:2)

简单而优雅。

function invertHex(hex {
  return (Number(`0x1${hex}`) ^ 0xFFFFFF).toString(16).substr(1).toUpperCase()
}

invertHex('00FF00'); // FF00FF

答案 7 :(得分:1)

这是一个简单的功能,可以反转粗麻布的颜色

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
}

Codepen example

答案 8 :(得分:1)

Onur 答案的 Python 替代方案:

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)

答案 9 :(得分:0)

用于反转元素颜色的功能。获取每个的亮度,如果它们很接近,则反转文本颜色。

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();
    }
}

下面的颜色“类别”。接受十六进制,rgb,rgba(即使有百分数),也可以输出到任意一个。资源管理器将需要String.padStartString.startsWith的polyfill,并且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;
}());

答案 10 :(得分:0)

适用于使用Ruby on Rails的用户。这是伟大的宝石 https://github.com/jfairbank/chroma

答案 11 :(得分:0)

对于打字稿爱好者,这里是我使用的:

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;
}

答案 12 :(得分:0)

可以使用代码片段转换 HEX 颜色

function invertColor(color) {
      return '#' + ("000000" + (0xFFFFFF ^ parseInt(color.substring(1),16)).toString(16)).slice(-6);
  }

答案 13 :(得分:0)

怎么样,CSS filter: invert(1),它有一个不错的 cross-browser compatibility,它可以处理文本和图像或您的任何内容。

对于黑白反转颜色添加更多过滤器filter: saturate(0) grayscale(1) brightness(.7) contrast(1000%) invert(1)

const i = document.querySelector("i");
const b = document.querySelector("b");
const input = document.querySelector("input");

input.oninput = (e) => {
  const color = e.target.value;
  i.style.background = color;
  b.style.color = color;
  b.innerText = color;
}
body {
  font-family: Arial;
  background: #333;
}

div {
  position: relative;
}

i {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  min-width: 100px;
  padding: .5em 1em;
  border: 2px solid #FFF;
  border-radius: 15px;
  background: #378ad3;
  font-style: normal;
}

b {
  /* Inverting the color */
  /* ᐯᐯᐯᐯᐯᐯᐯᐯᐯᐯᐯᐯ */
  filter: saturate(0) grayscale(1) brightness(.7) contrast(1000%) invert(1);
}

input {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}
<div>
  <i><b>#378ad3</b></i>
  <input type="color" value="#378ad3"/>
</div>