it-swarm.com.ru

Как я могу создать противоположный цвет в соответствии с текущим цветом?

Я пытаюсь создать цвет, противоположный текущему. Я имею в виду, если текущий цвет black, то мне нужно сгенерировать white.

На самом деле у меня есть текст (цвет этого текста динамический, его цвет можно сделать произвольно). Этот текст находится в div, и мне нужно установить противоположный цвет этого текста для background-color из div. Я хотел бы, чтобы этот текст был clear в 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_opp_color()?

35
stack

UPDATE: готовый к производству код на GitHub .


Вот как я это сделаю: 

  1. Конвертировать HEX в RGB
  2. Инвертировать компоненты R, G и B
  3. Конвертировать каждый компонент обратно в HEX
  4. Заполните каждый компонент нулями и выводом.
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

99
Onur Yıldırım

Простой способ добиться этого с помощью CSS:

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

В моем понимании вашего вопроса под противоположным цветом вы подразумеваете инвертированный цвет.

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

4
dn Fer

Остерегайтесь доступности (AA/AAA). Цветовой контраст сам по себе бесполезен. Действительно разные цвета могут вообще не иметь контраста для дальтоников .. ИМХО, расчет для такого цвета может выглядеть так:

(Используйте «HLS» для простоты)

  • Поверните оттенок на 180º, чтобы получить (возможно, бесполезный) максимальный цветовой контраст
  • Рассчитайте разницу яркости.
  • (Рассчитайте разницу в цвете ... ненужно, она максимальная или почти)
  • Рассчитайте коэффициент контрастности.
  • Если полученный цвет соответствует требованиям, вычисление требований заканчивается, если нет, цикл:
    • Если разница в яркости не достаточна, увеличьте или Уменьшите расчетную яркость цвета (L) на определенную величину или коэффициент (вверх или Вниз в зависимости от исходной яркости цвета:> или <, чем среднее значение )
    • Проверьте, соответствует ли он вашим требованиям, если он завершает расчет.
    • если яркость можно увеличить (или уменьшить) больше, то нет действующего цвета, который бы соответствовал требованиям, просто попробуйте черный и белый, выберите «лучший» из них (вероятно, с более высоким коэффициентом контрастности) и закончите.
4
miguel-svq

Просто и элегантно.

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

invertHex('00FF00'); // FF00FF
1
Gerard Lamusse

Простое переключение цвета фона на цвет текста не будет работать с некоторыми значениями среднего диапазона, например 0x808080. Вместо этого я попытался сместить значения цвета - (v + 0x80) % 0x100. Посмотреть демо здесь .

Согласитесь с комментарием от miguel-svq - хотя ожидаем увидеть более подробные алгоритмы для каждого шага расчета. 

1
jason_zhuyx

Функция для инвертирования цвета элемента. Получает яркость каждого и, если они близки, инвертирует цвет текста. 

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

Цвет "Класс" ниже. Принимает hex, rgb, rgba (даже с процентами), а также может выводить любой из них. Для String.padStart и String.startsWith обозревателю потребуются полифилы, а интерполированную строку в методе 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;
}());
0
Derek Ziemba