Как я могу создать противоположный цвет в соответствии с текущим цветом?
Я пытаюсь создать цвет, противоположный текущему. Я имею в виду, если текущий цвет черный, то мне нужно генерировать белый.
На самом деле у меня есть текст (цвет этого текста является динамическим, его цвет может быть сделан наугад). Этот текст находится в div
и мне нужно установить противоположный цвет этого текста для background-color
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_opp_color()
?
Ответы
Ответ 1
UPDATE: готовый к выпуску код на GitHub.
Вот как я это сделаю:
- Преобразование HEX в RGB
- Инвертировать компоненты R, G и B
- Преобразование каждого компонента обратно в HEX
- Поместите каждый компонент с нулями и выводами.
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);
}
Пример:
Расширенная версия:
У этого есть опция 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);
}
Пример:
Ответ 2
Простой способ добиться этого с помощью CSS:
mix-blend-mode: difference;
color:white;
Ответ 3
Просто и элегантно.
function invertHex(hex) {
return (Number('0x1${hex}') ^ 0xFFFFFF).toString(16).substr(1).toUpperCase()
}
invertHex('00FF00'); // Returns FF00FF
Ответ 4
Остерегайтесь доступности (AA/AAA). Цветовой контраст сам по себе бесполезен. На самом деле разные цвета могут не иметь никакого контраста для цветных слепых людей. ИМХО расчет для такого цвета может идти следующим образом:
(Для простоты используйте "HLS")
- Поверните Hue на 180º, чтобы получить (возможно, бесполезный) максимальный цветовой контраст
- Рассчитайте разницу яркости.
- (Рассчитайте разницу цветов... ненужный, максимальный или почти)
- Вычислить коэффициент контрастности.
- Если итоговый цвет соответствует завершению расчета требований, если нет, цикл:
- Если разница яркости недостаточно, увеличивайте или уменьшайте расчетную яркость цвета (L) на определенную величину или соотношение (вверх или вниз в зависимости от исходной яркости цвета:> или <чем среднее значение)
- Проверьте, соответствует ли он вашим требованиям, заканчивается ли расчет.
- если светимость может быть увеличена (или уменьшена), то не будет подходящего цвета для соответствия требованиям, просто попробуйте сделать черно-белый, возьмите "лучший" из них (возможно, тот, у кого больше контрастность) и закончите.
Ответ 5
В моем понимании вашего вопроса, противоположным цветом вы имеете в виду перевернутый цвет.
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
Ответ 6
Простое перемещение цвета фона в цвет текста не будет работать с некоторыми значениями среднего диапазона, например 0x808080
. Вместо этого я попытался изменить значения цвета - (v + 0x80) % 0x100
. См. Демонстрацию здесь.
Соглашаясь с комментарием от miguel-svq - хотя ожидаем увидеть более подробные алгоритмы для каждого шага расчета.
Ответ 7
Функция для инвертирования цвета элемента. Получает яркость каждого и, если они близки, инвертирует цвет текста.
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;
}());
Ответ 8
Это простая функция, которая инвертирует esadecimal цвет
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