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

<p>я пытаюсь создать цвет, противоположный текущему. я имею в виду, если текущий цвет <em>black</em>, то мне нужно сгенерировать <em>white</em>.</p><p>на самом деле у меня есть текст <em>(цвет этого текста динамический, его цвет можно сделать произвольно)</em>. этот текст находится в <code>div</code>, и мне нужно установить противоположный цвет этого текста для <code>background-color</code> из <code>div</code>. я хотел бы, чтобы этот текст был<strong> clear </strong>в <code>div</code> <em>(цветная перспектива)</em>.</p><blockquote> <p><strong> противоположный цвет </strong>означает: темный/яркий</p> </blockquote><p>у меня есть текущий цвет текста, и я могу передать его этой функции:</p><pre><code>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) </code></pre><p>есть ли идея создать функцию <code>create\_opp\_color()</code>?</p>

<p><strong>update</strong>: готовый к производству <strong>код на <a href="https://github.com/onury/invert-color">github</a> .</strong></p><hr><p>вот как я это сделаю: </p><ol> <li>конвертировать hex в rgb</li> <li>инвертировать компоненты r, g и b</li> <li>конвертировать каждый компонент обратно в hex</li> <li>заполните каждый компонент нулями и выводом.</li> </ol><pre class="lang-js prettyprint-override"><code>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); } </code></pre><p>пример вывода: </p><p> <a href="https://i.stack.imgur.com/1cbel.png"> <img src="https://i.stack.imgur.com/1cbel.png" alt="enter image description here"> </a> </p><p><strong>продвинутая версия:</strong> </p><p>у этого есть опция <code>bw</code>, которая решит, следует ли преобразовать в черный или белый; таким образом, вы получите больше контраста, который обычно лучше для человеческого глаза. </p><pre class="lang-js prettyprint-override"><code>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); } </code></pre><p>пример вывода:</p><p> <a href="https://i.stack.imgur.com/s82pu.png"> <img src="https://i.stack.imgur.com/s82pu.png" alt="enter image description here"> </a> </p>

<p>простой способ добиться этого с помощью css:</p><pre><code>mix-blend-mode: difference; color:white; </code></pre>

<p>в моем понимании вашего вопроса под противоположным цветом вы подразумеваете инвертированный цвет.</p><pre><code>invertedcolorcomponent = 0xff - colorcomponent </code></pre><p>таким образом, для красного цвета (# ff0000) это означает: r = 0xff или 255 g = 0x00 или 0 b = 0x00 или 0</p><p>красный перевернутый цвет (# 00ffff):</p><pre><code>r = 0xff - 0xff = 0x00 or 255 - 255 = 0 g = 0xff - 0x00 = 0xff or 255 - 0 = 255 b = 0xff - 0x00 = 0xff or 255 - 0 = 255 </code></pre><p>еще примеры:</p><p>черный (# 000000) становится белым (#ffffff).</p><p>оранжевый (# ffa500) становится # 005aff</p>

<p>остерегайтесь доступности (aa/aaa). цветовой контраст сам по себе бесполезен. действительно разные цвета могут вообще не иметь контраста для дальтоников .. имхо, расчет для такого цвета может выглядеть так:</p><p>(используйте «hls» для простоты)</p><ul> <li>поверните оттенок на 180º, чтобы получить (возможно, бесполезный) максимальный цветовой контраст</li> <li>рассчитайте разницу яркости.</li> <li>(рассчитайте разницу в цвете ... ненужно, она максимальная или почти)</li> <li>рассчитайте коэффициент контрастности.</li> <li>если полученный цвет соответствует требованиям, вычисление требований заканчивается, если нет, цикл: <ul> <li>если разница в яркости не достаточна, увеличьте или уменьшите расчетную яркость цвета (l) на определенную величину или коэффициент (вверх или вниз в зависимости от исходной яркости цвета:> или <, чем среднее значение )</li> <li>проверьте, соответствует ли он вашим требованиям, если он завершает расчет.</li> <li>если яркость можно увеличить (или уменьшить) больше, то нет действующего цвета, который бы соответствовал требованиям, просто попробуйте черный и белый, выберите «лучший» из них (вероятно, с более высоким коэффициентом контрастности) и закончите.</li> </ul></li> </ul>

<p>просто и элегантно.</p><pre><code>function inverthex(hex { return (number(`0x1${hex}`) ^ 0xffffff).tostring(16).substr(1).touppercase() } inverthex('00ff00'); // ff00ff </code></pre>

<p>простое переключение цвета фона на цвет текста не будет работать с некоторыми значениями среднего диапазона, например <code>0x808080</code>. вместо этого я попытался сместить значения цвета - <code>(v + 0x80) % 0x100</code>. посмотреть демо <a href="https://codepen.io/jason\_zhuyx/pen/vygrbd">здесь</a> .</p><p>согласитесь с комментарием от <a href="https://stackoverflow.com/a/35969938/4922856">miguel-svq</a> - хотя ожидаем увидеть более подробные алгоритмы для каждого шага расчета. </p>