Як розрахувати необхідний відтінок-поворот для створення певного кольору?


75

У мене є біле зображення, яке я використовую як фон для div, і я хотів би забарвити, щоб він відповідав основному кольору тем. Я усвідомлюю, що можу зробити:

filter: sepia() saturate(10000%) hue-rotate(30deg);

і прокрутити, hue-rotateщоб знайти колір, але чи можна обчислити це значення заздалегідь? Враховуючи, що вказане шістнадцяткове значення досить темне, я думаю, мені також потрібно буде включити invert(%)фільтр.

Враховуючи шістнадцяткове значення, #689d94яку математику мені потрібно зробити, щоб обчислити бажане hue-rotateі invertзначення для перетворення мого білого фонового зображення в один колір?

Редагувати

Ось фрагмент divіз білим фоновим зображенням, що відфільтровується зеленим. Фокус тут у divтому, що фільтрується все, а не лише зображення. Якби я ввів якийсь текст у divтекст, колір тексту також став би зеленим.

div {
  background:url(http://richard.parnaby-king.co.uk/basket.svg) no-repeat scroll 0 0 transparent;
  background-size:5em;
  width:5em;
  height:5em;
  -webkit-filter: invert(25%) sepia() saturate(100000%) hue-rotate(174deg);
  filter: invert(25%) sepia() saturate(100000%) hue-rotate(174deg);
}
<div>
  </div>


Так, це фактичне фонове зображення.
Річард Парнабі-Кінг

Потім (знову AFAIK) .. це неможливо, до фактичних зображень застосовуються фільтри.
Paulie_D

Які обмеження ви вводите у цьому питанні? Я думаю, що це може бути більш-менш досяжним за допомогою filter: url (#mySvgFilter). Для цього знадобиться можливість або включити елемент svg десь на сторінці, або десь розмістити файли SVG. Це було б життєздатним рішенням? Як не дивно, але я не зміг змусити колір точно відповідати (хоча вони повинні) при використанні кольорових матриць, але це може бути я, що я нерозумію щось, пов’язане з режимами змішування. Крім того, якщо я можу запитати, яку основну проблему ви намагаєтесь вирішити?
Йохан Перссон,

Спочатку я намагався зменшити кількість http-запитів, які повинен був зробити користувач, використовуючи лише одне зображення svg (кошик використовувався деінде на сторінці), і я просто хотів змінити колір за допомогою CSS. Врешті-решт, я використав два інших зображення (одне для темно-зеленого, вгорі, і одне в чорному), але це все ще питання, на яке я шукаю відповідь. Що стосується обмежень - я шукаю ряд кроків або процедуру, за якою я можу дотримуватися, що, отримуючи шістнадцятковий вхід, дає мені список фільтрів і значень, які мені потрібно використовувати для забарвлення мого білого зображення.
Річард Парнабі-Кінг

Чи можна використовувати вбудований фільтр svg?
Річард Парнабі-Кінг

Відповіді:


94

Ключовим у цьому випадку є визначення початкового кольору. Білий, чорний або будь-яка сіра шкала технічно є фактичним кольором - ви не можете наситити або повернути його. Вам доведеться це якось «забарвити», а фільтр сепії - єдиний фільтр, який виконує певну форму забарвлення.

Було б простіше, якби ваше зображення було чисто 100% червоним. Тоді ви можете просто додати цільовий градус безпосередньо та відрегулювати насиченість та легкість, використовуючи HSL для цілі. Для початкової точки білого кольору першим кроком є ​​перетворення та визначення проміжного кольору, щоб ми могли наситити та повернути його пізніше.

Давайте спочатку затемнимо біле зображення і застосуємо сепію, щоб отримати "базовий" колір, з яким ми можемо працювати:

filter: brightness(50%) sepia(1);

Це дозволить отримати значення кольору RGB приблизно:

rgb(178, 160, 128)

Крок другий - перетворити це на кольоровий простір HSL, що дає нам:

hsl(38, 24.5%, 60%);

Результат базового кольору

div {
  background:url(http://richard.parnaby-king.co.uk/basket.svg) no-repeat;
  background-size:5em;
  width:5em;
  height:5em;
  -webkit-filter: brightness(50%) sepia(1);
  filter: brightness(50%) sepia(1);
}
<div></div>

Перетворення базового кольору в цільовий

Ці два перші кроки є статичними, і їх результат буде повторно використаний кожного разу, коли нам потрібно буде знайти цільове коригування (фактичне значення сепії визначається в специфікації фільтрів SVG ).

Тепер нам потрібно розрахувати, що нам потрібно застосувати до цього базового кольору, щоб отримати цільовий колір. Спочатку перетворіть цільовий колір, наприклад # 689d94, як вказано в питанні, у HSL:

hsl(170, 21.3%, 51.2%);

Тоді ми повинні обчислити різницю між ними. Відтінок обчислюється простим відніманням бази від цілі. Те саме стосується насиченості та легкості, але оскільки ми припускаємо 100% базової величини, нам потрібно відняти результат від 100%, щоб у підсумку отримати різницю для накопичених значень:

H:  170 - 38             ->  132°
S:  100 + (24.5 - 21.3)  ->  103.2%  (relative to base 100% =  3.2%)
L:  100 + (51.2 - 60.0)  ->   91.2%  (relative to base 100% = -8.8%)

Перетворіть ці значення у рядок фільтра, додавши його до існуючого фільтра, а потім встановіть його на div:

/*      ------ base color ------  -------  new target -------------------------------*/
filter: brightness(50%) sepia(1)  hue-rotate(132deg) saturate(103.2%) brightness(91.2%);

І щоб встановити його, ви, мабуть, зробите щось подібне, якщо припустимо, що filter і divElement вже оголошені:

...
filter = "brightness(0.5) sepia(1) hue-rotate(132deg) saturate(103.2%) brightness(91.2%)";
divElement.style.filter = filter;
divElement.style.webkitFilter = filter;

Зауважте, що є ймовірні помилки округлення, оскільки RGB представляється цілим числом, тоді як HSL є плаваючою комою, тому фактичний результат може бути не точним, але він повинен наблизитися.

Живий приклад

div {
  background:url(http://richard.parnaby-king.co.uk/basket.svg) no-repeat;
  background-size:5em;
  width:5em;
  height:5em;
  -webkit-filter: 
      brightness(50%) sepia(1) hue-rotate(132deg) saturate(103.2%) brightness(91.2%);
  filter: 
      brightness(50%) sepia(1) hue-rotate(132deg) saturate(103.2%) brightness(91.2%);
}
<div></div>
<span style="font:14px sans-serif;padding:7px;color:#fff;background:#689d94">
Target color</span>

Життєздатними альтернативними варіантами є:

  • Попередньо визначте SVG з уже встановленим кольором.
  • Працюйте з HSL / RGB безпосередньо в JavaScript та модифікуйте дерево SVG кольором безпосередньо для фігури, а не за допомогою фільтрів. Фільтри є дорогими показниками продуктивності, особливо якщо багато з них пов’язані ланцюгами, як тут, і вони, крім того, є домінуючою частиною сторінки. Вони не підтримуються у всіх браузерах.


@ K3N У мене тут є дуже подібне запитання: stackoverflow.com/questions/45901333/… . Може, у вас є відповідь? Дякую!
Еміліо

11
Ця відповідь, на жаль, неправильна. він передбачає, що відтінок-поворот працює в просторі HSL. Це не. Поворот відтінку CSS базується на базовому повороті відтінку, визначеному в специфікації фільтра SVG - який не має поняття про кольоровий простір HSL. Погані результати - це не результат наближення з плаваючою точкою, а той факт, що обертання відтінків робить дику кількість відсікань до кольорів - особливо тих, що є "екстремальними" - з дуже нерівною кількістю R / G / B.
Michael Mullany

2
Це гарна спроба, але абсолютно оманлива.
shabunc

25

Прийнята відповідь неправильна. Поворот відтінків не зберігає насиченість або яскравість, і вам доведеться робити божевільну математику, щоб придумати правильні значення. Набагато простіший спосіб - що призведе до правильного результату - це зробити фільтр CSS, який посилається на фільтр SVG. Примітив feColorMatrix у фільтрах SVG дозволяє вибрати колір безпосередньо - на зразок цього. Візьміть свій колір # 424242 - розділіть шістнадцяткове значення кожного кольору на #FF (.257) і помістіть їх у п'ятий стовпець, перші три рядки вашої кольорової матриці. Подобається так:

div {
  background:url(http://richard.parnaby-king.co.uk/basket.svg) no-repeat scroll 0 0 transparent;
  background-size:5em;
  width:5em;
  height:5em;
  -webkit-filter: url(#colorize);
  filter: url(#colorize);
}
<div>
  </div>

<svg>
<defs>
<filter id="colorize" color-interpolation-filters="sRGB">
<feColorMatrix type="matrix" values="0 0 0 0 .257
                                 0 0 0 0 .257
                                 0 0 0 0 .257
                                 0 0 0 1 0"/>
 
/filter>
</defs>
</svg>


Це виглядає як гарне рішення. Але чи можете ви вказати мені, як отримати .257, .257, .257 з # 424242 та #FF? Я спробував зайти в шістнадцятковий калькулятор і зробити шістнадцятковий шрифт, поділений на шістнадцятковий FF, і він просто сказав мені шістнадцяткове значення: 0 Залишок: 42, Десяткове значення: 0 Залишок: 66.
mpavey

2
Hex # 42 = Десяткове число 4 * 16 + 2 = 66. 66/256 = .257
Michael Mullany

@MichaelMullany навіщо ділити на 256, а не на 255?
shabunc

Має бути 255 - вибачте.
Michael Mullany

0

Якщо використовується svg, тоді ...

Ви можете відкрити svg-файли за допомогою якогось текстового редактора, скопіювавши та вставивши у html-файл, а потім змінивши колір шляху за необхідності.

У наведеному нижче прикладі коду ... Я щойно змінив колір шляху центрального кільця. Сподіваюся, це допомагає ..

        var imgg =document.getElementById("path");
        imgg.style="fill:#424242";
   
<html>
<body>
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="imgg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 296.838 296.838" style="enable-background:new 0 0 296.838 296.838;" xml:space="preserve" width="512px" height="512px">
<g>
	<path  d="M58.733,64.566L41.763,47.596C14.832,74.526,0,110.333,0,148.419s14.832,73.893,41.763,100.823l16.971-16.971   C36.335,209.874,24,180.095,24,148.419S36.335,86.964,58.733,64.566z" fill="#91DC5A"/>
	<path d="M82.137,81.969c-17.75,17.748-27.525,41.348-27.525,66.45s9.775,48.702,27.525,66.45l16.971-16.971   c-13.218-13.216-20.496-30.788-20.496-49.479s7.278-36.264,20.496-49.48L82.137,81.969z" fill="#91DC5A"/>
	<path d="M255.075,47.596l-16.971,16.971c22.399,22.397,34.733,52.177,34.733,83.853s-12.335,61.455-34.733,83.852l16.971,16.971   c26.931-26.931,41.763-62.737,41.763-100.823S282.006,74.526,255.075,47.596z" fill="#91DC5A"/>
	<path d="M214.701,81.969L197.73,98.939c13.218,13.216,20.496,30.788,20.496,49.48s-7.278,36.264-20.496,49.479l16.971,16.971   c17.75-17.748,27.525-41.348,27.525-66.45S232.451,99.717,214.701,81.969z" fill="#91DC5A"/>
	<path id="path" d="M148.586,114.789c-8.607,0-17.212,3.284-23.78,9.851c-13.131,13.133-13.131,34.424,0,47.559   c6.568,6.566,15.174,9.851,23.78,9.851c8.606,0,17.212-3.284,23.779-9.851c13.131-13.135,13.131-34.426,0-47.559   C165.798,118.073,157.192,114.789,148.586,114.789z M155.395,155.228c-2.454,2.454-5.319,2.821-6.809,2.821   c-1.489,0-4.356-0.367-6.808-2.818c-3.755-3.756-3.755-9.867-0.003-13.619c2.455-2.455,5.321-2.822,6.811-2.822   c1.489,0,4.354,0.367,6.808,2.82C159.147,145.363,159.147,151.475,155.395,155.228z" fill="#91DC5A"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>
    
    
</body>
</html>

Для фонового зображення

        var myimg='url(\'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 296.838 296.838" style="enable-background:new 0 0 296.838 296.838;" xml:space="preserve" width="512px" height="512px"><g><path  d="M58.733,64.566L41.763,47.596C14.832,74.526,0,110.333,0,148.419s14.832,73.893,41.763,100.823l16.971-16.971   C36.335,209.874,24,180.095,24,148.419S36.335,86.964,58.733,64.566z" fill="#91DC5A"/><path d="M82.137,81.969c-17.75,17.748-27.525,41.348-27.525,66.45s9.775,48.702,27.525,66.45l16.971-16.971   c-13.218-13.216-20.496-30.788-20.496-49.479s7.278-36.264,20.496-49.48L82.137,81.969z" fill="#91DC5A"/><path d="M255.075,47.596l-16.971,16.971c22.399,22.397,34.733,52.177,34.733,83.853s-12.335,61.455-34.733,83.852l16.971,16.971   c26.931-26.931,41.763-62.737,41.763-100.823S282.006,74.526,255.075,47.596z" fill="#91DC5A"/><path d="M214.701,81.969L197.73,98.939c13.218,13.216,20.496,30.788,20.496,49.48s-7.278,36.264-20.496,49.479l16.971,16.971   c17.75-17.748,27.525-41.348,27.525-66.45S232.451,99.717,214.701,81.969z" fill="#91DC5A"/><path d="M148.586,114.789c-8.607,0-17.212,3.284-23.78,9.851c-13.131,13.133-13.131,34.424,0,47.559   c6.568,6.566,15.174,9.851,23.78,9.851c8.606,0,17.212-3.284,23.779-9.851c13.131-13.135,13.131-34.426,0-47.559   C165.798,118.073,157.192,114.789,148.586,114.789z M155.395,155.228c-2.454,2.454-5.319,2.821-6.809,2.821   c-1.489,0-4.356-0.367-6.808-2.818c-3.755-3.756-3.755-9.867-0.003-13.619c2.455-2.455,5.321-2.822,6.811-2.822   c1.489,0,4.354,0.367,6.808,2.82C159.147,145.363,159.147,151.475,155.395,155.228z" fill="#91DC5A"/></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></svg> \')';
        
        document.getElementById("mydiv").style.backgroundImage =myimg ;  
        
        
        
        //changing color according to theme .. new theme color :#424242
        myimg=myimg.replace(/#91DC5A/g,"#424242");
       document.getElementById("mydiv").style.backgroundImage =myimg ; 
             div {

  background-size:5em;
  width:5em;
  height:5em;
  
}
<html>
<body>

    
    <div id="mydiv"></div>
<span style="font:14px sans-serif;padding:7px;color:#fff;background:#689d94">
Target color</span>
   
  
    
</body>
</html>


Має бути фоновим зображенням.
Річард Парнабі-Кінг

@ RichardParnaby-King також додав кейс для фонових зображень .. Я б використовував z-index для створення фонового зображення .. у будь-якому випадку .. я зробив обхідний шлях для фонового зображення
Азі,

svg також можна використовувати як фонові зображення.
Erkin Alp Güney
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.