web-dev-qa-db-fra.com

Comment calculer la teinte-rotation requise pour générer une couleur spécifique?

J'ai une image blanche que j'utilise comme arrière-plan pour une div, et j'aimerais colorier la couleur principale du thème. Je suis conscient que je peux faire:

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

et parcourez hue-rotate pour trouver une couleur, mais est-il possible de calculer cette valeur à l'avance? Étant donné que la valeur hexadécimale spécifiée est assez sombre, j'imagine que je devrais également inclure le filtre invert(%).

Avec une valeur hexadécimale de #689d94, que dois-je faire en calcul pour calculer les valeurs désirées hue-rotate et invert afin de convertir mon image de fond blanc dans la même couleur?

Modifier

Voici un extrait d'une div avec une image d'arrière-plan blanche filtrée en vert. Le truc ici, c’est que c’est l’ensemble de la div qui est filtrée, pas seulement l’image. Si je devais saisir du texte dans la variable div, la couleur du texte deviendrait également verte.

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>

47

La clé dans ce cas est de définir une couleur initiale. Le blanc, le noir ou n'importe quelle échelle de gris est techniquement une couleur réelle - vous ne pouvez pas la saturer ni la faire pivoter. Vous devrez le "coloriser" en quelque sorte, et le filtre sépia est le seul filtre qui effectue une certaine forme de colorisation.

Ce serait plus facile si votre image était 100% rouge pur. Ensuite, vous pouvez simplement ajouter directement le degré de cible et régler la saturation et la luminosité en utilisant HSL comme cible. Pour un point de départ de couleur blanche, la première étape consiste à convertir et à définir une couleur intermédiaire afin que nous puissions la saturer et la faire pivoter ultérieurement.

Permet d'abord d'assombrir l'image blanche et d'appliquer le sépia pour obtenir une couleur "de base" avec laquelle nous pouvons travailler:

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

Cela produira une valeur de couleur RVB d'environ:

rgb(178, 160, 128)

La deuxième étape consiste à convertir cela en espace couleur HSL qui nous donne:

hsl(38, 24.5%, 60%);

Résultat couleur de base

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>

Conversion de la couleur de base en couleur cible

Ces deux premières étapes sont statiques et son résultat sera réutilisé chaque fois que nous aurons besoin de trouver un ajustement cible (la valeur réelle de sepia est définie dans la spécification Filtres SVG ).

Maintenant, nous devons calculer ce que nous devons appliquer à cette couleur de base pour obtenir la couleur cible. Commencez par convertir la couleur cible, par exemple # 689d94, comme indiqué dans la question, en HSL:

hsl(170, 21.3%, 51.2%);

Ensuite, nous devons calculer la différence entre ceux-ci. La teinte est calculée en soustrayant simplement la base de la cible. Même chose pour Saturation et Luminosité, mais comme nous supposons 100% de la valeur de base, nous devons soustraire le résultat de 100% pour obtenir un diff pour les valeurs accumulées:

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

Convertissez ces valeurs en chaîne de filtre en l'ajoutant au filtre existant, puis définissez-la sur la div:

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

Et pour le définir, vous feriez probablement quelque chose comme ceci en supposant que filter et divElement sont déjà déclarés:

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

Notez qu'il existe probablement des erreurs d'arrondi, car RVB est représenté sous la forme d'un entier, HSL étant une virgule flottante. Par conséquent, le résultat réel peut ne pas être exact, mais il devrait être très proche.

Exemple en direct

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>

Les alternatives viables sont:

  • Prédéfinissez les SVG avec la couleur déjà définie.
  • Utilisez HSL/RGB directement en JavaScript et modifiez l'arborescence SVG avec la couleur directement pour la forme plutôt qu'en utilisant des filtres. Les filtres coûtent cher en termes de performances, surtout si beaucoup sont chaînés comme ici et qu’ils constituent en outre une partie dominante d’une page. Ils ne sont pas pris en charge dans tous les navigateurs.
58
user1693593

La réponse acceptée est fausse. Teinte-Rotation ne conserve pas la saturation ni la luminosité et vous devez faire des calculs loufoques pour obtenir les valeurs correctes. Le moyen le plus simple - ce qui donnera un résultat correct - consiste à créer un filtre CSS faisant référence à un filtre SVG. La primitive feColorMatrix dans les filtres SVG vous permet de choisir directement une couleur - comme cela. Prenez votre couleur # 424242 - divisez la valeur hexadécimale de chaque couleur par #FF (.257) et mettez-les dans la cinquième colonne, les trois premières lignes de votre matrice de couleurs. Ainsi:

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>

11
Michael Mullany

Si svg est utilisé alors ...

Vous pouvez ouvrir des fichiers svg avec un éditeur de texte copier et coller dans un fichier html, puis changer la couleur du chemin si nécessaire.

Dans l'exemple de code ci-dessous ... Je viens de changer la couleur du chemin de l'anneau central. J'espère que cela t'aides..

        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>

Pour l'image de fond

        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>

0
Azi