Wie berechnet man die erforderliche Farbtonrotation, um eine bestimmte Farbe zu erzeugen?

75

Ich habe ein weißes Bild, das ich als Hintergrund für ein Div verwende, und ich möchte es farblich an die Hauptfarbe des Themas anpassen. Ich bin mir bewusst, dass ich Folgendes tun kann:

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

und durchlaufen hue-rotate, um eine Farbe zu finden, aber ist es möglich, diesen Wert im Voraus zu berechnen? Angesichts der Tatsache, dass der angegebene Hex-Wert ziemlich dunkel ist, kann ich mir vorstellen, dass ich auch den invert(%)Filter einbeziehen muss.

Bei einem hexadezimalen Wert von #689d94was muss ich rechnen, um den gewünschten Wert hue-rotateund den invertWert zu berechnen, um mein weißes Hintergrundbild in dieselbe Farbe umzuwandeln?

Bearbeiten

Hier ist ein Ausschnitt von a divmit einem weißen Hintergrundbild, das grün gefiltert wird. Der Trick dabei ist, dass das Ganze divgefiltert wird, nicht nur das Bild. Wenn ich Text in divdie Textfarbe eingeben würde, würde diese ebenfalls grün werden.

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>

Richard Parnaby-King
quelle
Ja, es ist ein tatsächliches Hintergrundbild.
Richard Parnaby-King
Dann (wieder AFAIK) .. das ist nicht möglich, Filter werden auf tatsächliche Bilder angewendet.
Paulie_D
Welche Einschränkungen legen Sie in dieser Frage fest? Ich denke, dass dies mit filter: url (#mySvgFilter) mehr oder weniger erreichbar sein könnte. Dies würde erfordern, dass entweder irgendwo auf der Seite ein SVG-Element eingefügt oder irgendwo eine SVG-Datei gehostet werden kann. Wäre das eine praktikable Lösung? Seltsamerweise konnte ich bei der Verwendung von Farbmatrizen nicht genau die Farbe finden (obwohl dies der Fall sein sollte), aber das könnte sein, dass ich etwas im Zusammenhang mit Mischmodi falsch verstehe. Wenn ich fragen darf, was ist das zugrunde liegende Problem, das Sie zu lösen versuchen?
Johan Persson
Ursprünglich habe ich versucht, die Anzahl der http-Anfragen zu reduzieren, die ein Benutzer stellen muss, indem er nur das eine SVG-Bild verwendet (der Warenkorb wurde an anderer Stelle auf der Seite verwendet), und ich wollte nur die Farbe mithilfe von CSS ändern. Letztendlich habe ich zwei andere Bilder verwendet (eines für das Dunkelgrün oben und eines in Schwarz), aber dies ist immer noch eine Frage, auf die ich nach einer Antwort suche. Was Einschränkungen betrifft - Ich suche nach einer Reihe von Schritten oder einer Prozedur, die ich befolgen kann, um bei einer Hex-Eingabe eine Liste von Filtern und Werten zu erhalten, die ich zum Färben meines weißen Bildes verwenden muss.
Richard Parnaby-King
Ist es möglich, einen Inline-SVG-Filter zu verwenden?
Richard Parnaby-King

Antworten:

93

In diesem Fall besteht der Schlüssel darin, eine Anfangsfarbe zu definieren. Weiß, Schwarz oder Graustufen sind technisch gesehen eine tatsächliche Farbe - Sie können sie nicht sättigen oder drehen. Sie müssen es irgendwie "kolorieren", und der Sepia-Filter ist der einzige Filter, der irgendeine Form des Kolorierens ausführt.

Es wäre einfacher, wenn Ihr Bild zu 100% rot wäre. Dann können Sie einfach den Zielgrad direkt hinzufügen und die Sättigung und Helligkeit mithilfe von HSL für das Ziel anpassen. Für einen Startpunkt für weiße Farben besteht der erste Schritt darin, eine Zwischenfarbe zu konvertieren und zu definieren, damit wir sie später sättigen und drehen können.

Lassen Sie uns zuerst das weiße Bild abdunkeln und Sepia auftragen, um eine "Grundfarbe" zu erhalten, mit der wir arbeiten können:

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

Dies erzeugt einen RGB-Farbwert von ungefähr:

rgb(178, 160, 128)

Schritt zwei besteht darin , dies in einen HSL-Farbraum umzuwandeln, der uns Folgendes gibt:

hsl(38, 24.5%, 60%);

Grundfarbenergebnis

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>

Konvertieren der Grundfarbe in die Zielfarbe

Diese beiden ersten Schritte sind statisch und das Ergebnis wird jedes Mal wiederverwendet, wenn wir eine Zielanpassung finden müssen (der tatsächliche Wert von Sepia ist in der SVG-Filterspezifikation definiert ).

Jetzt müssen wir berechnen, was wir auf diese Grundfarbe anwenden müssen, um die Zielfarbe zu erhalten. Konvertieren Sie zuerst die Zielfarbe, z. B. # 689d94, wie in der Frage angegeben, in HSL:

hsl(170, 21.3%, 51.2%);

Dann müssen wir die Differenz zwischen diesen berechnen. Der Farbton wird berechnet, indem einfach die Basis vom Ziel subtrahiert wird. Das Gleiche gilt für Sättigung und Helligkeit, aber da wir 100% des Basiswerts annehmen, müssen wir das Ergebnis von 100% subtrahieren, um einen Unterschied für die akkumulierten Werte zu erhalten:

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%)

Konvertieren Sie diese Werte in eine Filterzeichenfolge, indem Sie sie an den vorhandenen Filter anhängen und dann auf div setzen:

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

Und um es einzustellen, würden Sie wahrscheinlich so etwas tun, vorausgesetzt, Filter und DivElement sind bereits deklariert:

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

Beachten Sie, dass es wahrscheinlich Rundungsfehler gibt, da RGB als Ganzzahl dargestellt wird, während HSL Gleitkomma ist, sodass das tatsächliche Ergebnis möglicherweise nicht genau ist, aber ziemlich nahe kommen sollte.

Live-Beispiel

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>

Realisierbare alternative Optionen sind:

  • Definieren Sie SVGs mit der bereits eingestellten Farbe vor.
  • Arbeiten Sie mit HSL / RGB direkt in JavaScript und ändern Sie den SVG-Baum mit der Farbe direkt für die Form, anstatt Filter zu verwenden. Filter sind in Bezug auf die Leistung teuer, insbesondere wenn viele wie hier verkettet sind und außerdem einen dominanten Teil einer Seite darstellen. Sie werden nicht in allen Browsern unterstützt.
Gemeinschaft
quelle
9
Es ist auch erwähnenswert, dass die
Farbtonrotation
@ K3N Ich habe hier eine sehr ähnliche Frage: stackoverflow.com/questions/45901333/… . Vielleicht hast du die Antwort? Vielen Dank!
Emilio
11
Diese Antwort ist leider falsch. Es wird davon ausgegangen, dass die Farbtonrotation im HSL-Raum ausgeführt wird. Es tut nicht. Die CSS-Farbtonrotation basiert auf einer zugrunde liegenden Farbtonrotation, die in der SVG-Filterspezifikation definiert ist und keine Vorstellung vom HSL-Farbraum hat. Die schlechten Ergebnisse sind nicht das Ergebnis einer Gleitkomma-Approximation, sondern der Tatsache, dass das Drehen des Farbtons zu starken Übersteuerungen an Farben - insbesondere solchen, die "extrem" sind - mit sehr ungleichen Mengen an R / G / B führt.
Michael Mullany
2
Dies ist ein schöner Versuch, aber völlig irreführend.
Shabunc
25

Die akzeptierte Antwort ist falsch. Durch Drehen des Farbtons wird weder Sättigung noch Helligkeit erhalten, und Sie müssen verrückte Berechnungen durchführen, um die richtigen Werte zu erhalten. Der weitaus einfachere Weg - der zu einem korrekten Ergebnis führt - besteht darin, einen CSS-Filter zu erstellen, der auf einen SVG-Filter verweist. Mit dem Grundelement feColorMatrix in SVG-Filtern können Sie eine Farbe direkt auswählen. Nehmen Sie Ihre Farbe # 424242 - dividieren Sie den Hex-Wert jeder Farbe durch #FF (.257) und setzen Sie sie in die fünfte Spalte, die ersten drei Zeilen Ihrer Farbmatrix. Wie so:

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>

Michael Mullany
quelle
Das sieht nach einer guten Lösung aus. Aber können Sie mir zeigen, wie ich .257, .257, .257 von # 424242 und #FF bekomme? Ich habe versucht, zu einem Hex-Rechner zu gehen und Hex 42 geteilt durch Hex FF zu machen, und es hat mir nur gesagt, Hex-Wert: 0 Rest: 42, Dezimalwert: 0 Rest: 66.
mpavey
2
Hex # 42 = Dezimal 4 * 16 + 2 = 66. 66/256 = .257
Michael Mullany
@ MichaelMullany warum durch 256 teilen, nicht durch 255?
Shabunc
Sollte 255 sein - sorry.
Michael Mullany
0

Wenn svg verwendet werden, dann ...

Sie können SVG-Dateien mit einem Texteditor öffnen, kopieren und in eine HTML-Datei einfügen und dann die Pfadfarbe nach Bedarf ändern.

Im folgenden Beispielcode ... habe ich gerade die Pfadfarbe des Mittelrings geändert. Hoffe das hilft..

        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>

Für Hintergrundbild

        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>

Azi
quelle
Muss ein Hintergrundbild sein.
Richard Parnaby-King
@ RichardParnaby-King fügte Hintergrundbild Fall auch .. Ich hätte Z-Index verwendet, um Bild Hintergrund zu machen .. sowieso .. Ich habe eine Problemumgehung für Hintergrundbild gemacht
Azi
SVGs können auch als Hintergrundbilder verwendet werden.
Erkin Alp Güney