web-dev-qa-db-fra.com

Éclaircir ou assombrir par programme une couleur hexadécimale (ou rgb, et mélanger les couleurs)

Voici une fonction sur laquelle je travaillais pour éclaircir ou assombrir par programmation une couleur hexadécimale d'une quantité spécifique. Il suffit de passer une chaîne de caractères telle que "3F6D2A" pour la couleur (col) et un nombre entier base10 (amt) pour le montant à éclaircir ou assombrir. Pour foncer, indiquez un nombre négatif (par exemple -20).

La raison pour laquelle j'ai fait cela était à cause de toutes les solutions que j'ai trouvées, jusqu'à présent, elles semblaient trop compliquer le problème. Et j’ai eu l’impression que cela pourrait être fait avec quelques lignes de code. S'il vous plaît laissez-moi savoir si vous rencontrez des problèmes, ou avez des ajustements à faire qui accéléreraient.

function LightenDarkenColor(col,amt) {
    col = parseInt(col,16);
    return (((col & 0x0000FF) + amt) | ((((col>> 8) & 0x00FF) + amt) << 8) | (((col >> 16) + amt) << 16)).toString(16);
}

Pour le développement, voici une version plus facile à lire:

function LightenDarkenColor(col,amt) {
    var num = parseInt(col,16);
    var r = (num >> 16) + amt;
    var b = ((num >> 8) & 0x00FF) + amt;
    var g = (num & 0x0000FF) + amt;
    var newColor = g | (b << 8) | (r << 16);
    return newColor.toString(16);
}

Et enfin une version pour gérer les couleurs qui peuvent (ou ne peuvent pas) avoir le "#" au début. Plus ajustement pour les valeurs de couleur incorrectes:

function LightenDarkenColor(col,amt) {
    var usePound = false;
    if ( col[0] == "#" ) {
        col = col.slice(1);
        usePound = true;
    }

    var num = parseInt(col,16);

    var r = (num >> 16) + amt;

    if ( r > 255 ) r = 255;
    else if  (r < 0) r = 0;

    var b = ((num >> 8) & 0x00FF) + amt;

    if ( b > 255 ) b = 255;
    else if  (b < 0) b = 0;

    var g = (num & 0x0000FF) + amt;

    if ( g > 255 ) g = 255;
    else if  ( g < 0 ) g = 0;

    return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
}

OK, donc maintenant, il ne s’agit pas seulement de quelques lignes, mais cela semble beaucoup plus simple. Si vous n’utilisez pas le "#" et n’avez pas besoin de vérifier les couleurs en dehors de la plage, ce n’est que quelques lignes.

Si vous n'utilisez pas le "#", vous pouvez simplement l'ajouter dans le code suivant:

var myColor = "3F6D2A";
myColor = LightenDarkenColor(myColor,10);
thePlaceTheColorIsUsed = ("#" + myColor);

Je suppose que ma question principale est, est-ce que j'ai raison ici? Cela n’englobe-t-il pas certaines situations (normales)?

441
Pimp Trizkit

Eh bien, cette réponse est devenue sa propre bête. Beaucoup de nouvelles versions, ça devenait bête longtemps. Un grand merci à tous les nombreux contributeurs à cette réponse. Mais, afin de garder les choses simples pour les masses. J'ai archivé toutes les versions/l'historique de l'évolution de cette réponse sur mon github . Et tout a été nettoyé sur StackOverflow ici avec la dernière version. Un merci spécial à Mike 'Pomax' Kamermans pour cette version. Il m'a donné le nouveau calcul.


Cette fonction (pSBC) prendra une couleur Web HEX ou RGB. pSBC peut assombrir les nuances, ou les mélanger avec une deuxième couleur, et peut également les transmettre, mais les convertir de Hex en RGB (Hex2RGB) ou de RGB en Hex (RGB2Hex). Tout cela sans même que vous sachiez quel format de couleur vous utilisez.

Cela fonctionne très vite, probablement le plus rapide, surtout compte tenu de ses nombreuses fonctionnalités. Il y avait longtemps dans la fabrication. Voir toute l'histoire sur mon github . Si vous souhaitez utiliser le moyen le plus petit et le plus rapide pour ombrer ou mélanger, reportez-vous aux fonctions micro ci-dessous et utilisez l'un des démons à vitesse double. Ils sont parfaits pour les animations intenses, mais cette version est assez rapide pour la plupart des animations.

Cette fonction utilise la fusion de journal ou la fusion linéaire. Cependant, il ne se convertit PAS en HSL pour éclaircir ou assombrir correctement une couleur. Par conséquent, les résultats de cette fonction seront différents de ceux des fonctions beaucoup plus volumineuses et beaucoup plus lentes qui utilisent HSL.

jsFiddle avec pSBC

github> pSBC Wiki

Fonctionnalités:

  • Détecte automatiquement et accepte les couleurs Hex standard sous la forme de chaînes. Par exemple: "#AA6622" ou "#bb551144".
  • Détecte et accepte automatiquement les couleurs RVB standard sous la forme de chaînes. Par exemple: "rgb(123,45,76)" ou "rgba(45,15,74,0.45)".
  • Nuances de couleurs au blanc ou noir en pourcentage.
  • Mélange les couleurs en pourcentage.
  • Effectue la conversion Hex2RGB et RGB2Hex en même temps ou en solo.
  • Accepte les codes de couleur HEX à 3 chiffres (ou 4 chiffres avec alpha), sous la forme #RGB (ou #RGBA). Cela les élargira. Par exemple: "#C41" devient "#CC4411".
  • Accepte et (linéaire) mélange les canaux alpha. Si la couleur c0 (de) ou la couleur c1 (à) a un canal alpha, alors la couleur renvoyée aura un canal alpha. Si les deux couleurs ont un canal alpha, la couleur renvoyée sera un mélange linéaire des deux canaux alpha en utilisant le pourcentage indiqué (comme s'il s'agissait d'un canal de couleur normal). Si une seule des deux couleurs possède un canal alpha, cet alpha sera simplement transmis à la couleur renvoyée. Cela permet de mélanger/nuancer une couleur transparente tout en maintenant le niveau de transparence. Ou, si les niveaux de transparence doivent également se mélanger, assurez-vous que les deux couleurs ont des alphas. Lors de l'ombrage, le canal alpha passe directement à travers. Si vous voulez une ombrage de base qui ombrage également le canal alpha, utilisez rgb(0,0,0,1) ou rgb(255,255,255,1) comme couleur c1 (à) couleur (ou leurs équivalents hexadécimaux). Pour les couleurs RVB, le canal alpha de la couleur renvoyée sera arrondi à 3 décimales.
  • Les conversions RGB2Hex et Hex2RGB sont implicites lors de l'utilisation de la fusion. Indépendamment de la couleur c0 (de); la couleur renvoyée sera toujours au format couleur de la couleur c1 (to), s'il en existe une. S'il n'y a pas de couleur c1 (à), passez 'c' en tant que couleur c1 et il nuira et convertira ce que sera la couleur c0. Si vous ne souhaitez que la conversion, indiquez également 0 dans le pourcentage (p). Si la couleur c1 est omise ou si une erreur est transmise, elle ne sera pas convertie.
  • Une fonction secondaire est également ajoutée au global. pSBCr peut recevoir une couleur hexadécimale ou RVB et renvoie un objet contenant cette information de couleur. Son sous la forme: {r: XXX, g: XXX, b: XXX, a: X.XXX}. Où .r, .g et .b vont de 0 à 255. Et lorsqu'il n'y a pas d'alpha: .a vaut -1. Sinon: .a est compris entre 0.000 et 1.000.
  • Pour la sortie RVB, il sort rgba() sur rgb() lorsqu'une couleur avec un canal alpha a été transmise à c0 (de) et/ou c1 (à).
  • La vérification d'erreur mineure a été ajoutée. Ce n'est pas parfait Il peut encore planter ou créer un charabia. Mais ça va attraper des trucs. Fondamentalement, si la structure est erronée à certains égards ou si le pourcentage n'est pas un nombre ou ne relève pas de la portée, il retournera null. Un exemple: pSBC(0.5,"salt") == null, où il pense que #salt est une couleur valide. Supprimez les quatre lignes qui se terminent par return null; pour supprimer cette fonctionnalité et la rendre plus rapide et plus petite.
  • Utilise le mélange de journaux. Passez true dans pour l (le 4ème paramètre) pour utiliser le mélange linéaire.

Code:

// Version 4.0
const pSBC=(p,c0,c1,l)=>{
    let r,g,b,P,f,t,h,i=parseInt,m=Math.round,a=typeof(c1)=="string";
    if(typeof(p)!="number"||p<-1||p>1||typeof(c0)!="string"||(c0[0]!='r'&&c0[0]!='#')||(c1&&!a))return null;
    if(!this.pSBCr)this.pSBCr=(d)=>{
        let n=d.length,x={};
        if(n>9){
            [r,g,b,a]=d=d.split(","),n=d.length;
            if(n<3||n>4)return null;
            x.r=i(r[3]=="a"?r.slice(5):r.slice(4)),x.g=i(g),x.b=i(b),x.a=a?parseFloat(a):-1
        }else{
            if(n==8||n==6||n<4)return null;
            if(n<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(n>4?d[4]+d[4]:"");
            d=i(d.slice(1),16);
            if(n==9||n==5)x.r=d>>24&255,x.g=d>>16&255,x.b=d>>8&255,x.a=m((d&255)/0.255)/1000;
            else x.r=d>>16,x.g=d>>8&255,x.b=d&255,x.a=-1
        }return x};
    h=c0.length>9,h=a?c1.length>9?true:c1=="c"?!h:false:h,f=pSBCr(c0),P=p<0,t=c1&&c1!="c"?pSBCr(c1):P?{r:0,g:0,b:0,a:-1}:{r:255,g:255,b:255,a:-1},p=P?p*-1:p,P=1-p;
    if(!f||!t)return null;
    if(l)r=m(P*f.r+p*t.r),g=m(P*f.g+p*t.g),b=m(P*f.b+p*t.b);
    else r=m((P*f.r**2+p*t.r**2)**0.5),g=m((P*f.g**2+p*t.g**2)**0.5),b=m((P*f.b**2+p*t.b**2)**0.5);
    a=f.a,t=t.a,f=a>=0||t>=0,a=f?a<0?t:t<0?a:a*P+t*p:0;
    if(h)return"rgb"+(f?"a(":"(")+r+","+g+","+b+(f?","+m(a*1000)/1000:"")+")";
    else return"#"+(4294967296+r*16777216+g*65536+b*256+(f?m(a*255):0)).toString(16).slice(1,f?undefined:-2)
}

Usage:

// Setup:

let color1 = "rgb(20,60,200)";
let color2 = "rgba(20,60,200,0.67423)";
let color3 = "#67DAF0";
let color4 = "#5567DAF0";
let color5 = "#F3A";
let color6 = "#F3A9";
let color7 = "rgb(200,60,20)";
let color8 = "rgba(200,60,20,0.98631)";

// Tests:

/*** Log Blending ***/
// Shade (Lighten or Darken)
pSBC ( 0.42, color1 ); // rgb(20,60,200) + [42% Lighter] => rgb(166,171,225)
pSBC ( -0.4, color5 ); // #F3A + [40% Darker] => #c62884
pSBC ( 0.42, color8 ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(225,171,166,0.98631)

// Shade with Conversion (use "c" as your "to" color)
pSBC ( 0.42, color2, "c" ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #a6abe1ac

// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
pSBC ( 0, color6, "c" ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)

// Blending
pSBC ( -0.5, color2, color8 ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(142,60,142,0.83)
pSBC ( 0.7, color2, color7 ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(168,60,111,0.67423)
pSBC ( 0.25, color3, color7 ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(134,191,208)
pSBC ( 0.75, color7, color3 ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #86bfd0

/*** Linear Blending ***/
// Shade (Lighten or Darken)
pSBC ( 0.42, color1, false, true ); // rgb(20,60,200) + [42% Lighter] => rgb(119,142,223)
pSBC ( -0.4, color5, false, true ); // #F3A + [40% Darker] => #991f66
pSBC ( 0.42, color8, false, true ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(223,142,119,0.98631)

// Shade with Conversion (use "c" as your "to" color)
pSBC ( 0.42, color2, "c", true ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #778edfac

// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
pSBC ( 0, color6, "c", true ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)

// Blending
pSBC ( -0.5, color2, color8, true ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(110,60,110,0.83)
pSBC ( 0.7, color2, color7, true ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(146,60,74,0.67423)
pSBC ( 0.25, color3, color7, true ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(127,179,185)
pSBC ( 0.75, color7, color3, true ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #7fb3b9

/*** Other Stuff ***/
// Error Checking
pSBC ( 0.42, "#FFBAA" ); // #FFBAA + [42% Lighter] => null  (Invalid Input Color)
pSBC ( 42, color1, color5 ); // rgb(20,60,200) + #F3A + [4200% Blend] => null  (Invalid Percentage Range)
pSBC ( 0.42, {} ); // [object Object] + [42% Lighter] => null  (Strings Only for Color)
pSBC ( "42", color1 ); // rgb(20,60,200) + ["42"] => null  (Numbers Only for Percentage)
pSBC ( 0.42, "salt" ); // salt + [42% Lighter] => null  (A Little Salt is No Good...)

// Error Check Fails (Some Errors are not Caught)
pSBC ( 0.42, "#salt" ); // #salt + [42% Lighter] => #a5a5a500  (...and a Pound of Salt is Jibberish)

// Ripping
pSBCr ( color4 ); // #5567DAF0 + [Rip] => [object Object] => {'r':85,'g':103,'b':218,'a':0.941}

L'image ci-dessous aidera à montrer la différence entre les deux méthodes de fusion:


Fonctions micro

Si vous voulez vraiment la vitesse et la taille, vous devrez utiliser RVB et non HEX. Le mode RVB est plus simple et plus simple, HEX écrit trop lentement et se présente sous un trop grand nombre de goûts pour un simple support à deux lignes (par exemple, il peut s'agir d'un code HEX à 3, 4, 6 ou 8 chiffres). Vous devrez également sacrifier certaines fonctionnalités, aucune vérification d'erreur, pas de HEX2RGB ni de RGB2HEX. De plus, vous devrez choisir une fonction spécifique (basée sur le nom de la fonction ci-dessous) pour les calculs de fusion des couleurs, et si vous souhaitez un fondu ou une fusion. Ces fonctions prennent en charge les canaux alpha. Et lorsque les deux couleurs d’entrée ont des alphas, il les fusionne de manière linéaire. Si une seule des deux couleurs possède un alpha, il le transmettra directement à la couleur résultante. Voici deux fonctions de doublure incroyablement rapides et petites:

const RGB_Linear_Blend=(p,c0,c1)=>{
    var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,d=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
    return"rgb"+(x?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+i(e[3]=="a"?e.slice(5):e.slice(4))*p)+","+r(i(b)*P+i(f)*p)+","+r(i(c)*P+i(g)*p)+d;
}

const RGB_Linear_Shade=(p,c)=>{
    var i=parseInt,r=Math.round,[a,b,c,d]=c.split(","),P=p<0,t=P?0:255*p,P=P?1+p:1-p;
    return"rgb"+(d?"a(":"(")+r(i(a[3]=="a"?a.slice(5):a.slice(4))*P+t)+","+r(i(b)*P+t)+","+r(i(c)*P+t)+(d?","+d:")");
}

const RGB_Log_Blend=(p,c0,c1)=>{
    var i=parseInt,r=Math.round,P=1-p,[a,b,c,d]=c0.split(","),[e,f,g,h]=c1.split(","),x=d||h,d=x?","+(!d?h:!h?d:r((parseFloat(d)*P+parseFloat(h)*p)*1000)/1000+")"):")";
    return"rgb"+(x?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+p*i(e[3]=="a"?e.slice(5):e.slice(4))**2)**0.5)+","+r((P*i(b)**2+p*i(f)**2)**0.5)+","+r((P*i(c)**2+p*i(g)**2)**0.5)+d;
}

const RGB_Log_Shade=(p,c)=>{
    var i=parseInt,r=Math.round,[a,b,c,d]=c.split(","),P=p<0,t=P?0:p*255**2,P=P?1+p:1-p;
    return"rgb"+(d?"a(":"(")+r((P*i(a[3]=="a"?a.slice(5):a.slice(4))**2+t)**0.5)+","+r((P*i(b)**2+t)**0.5)+","+r((P*i(c)**2+t)**0.5)+(d?","+d:")");
}

Vous voulez plus d'informations? Lisez le texte complet sur github .

PT

(P.s.Si quelqu'un a le calcul pour une autre méthode de mélange, partagez-le.)

841
Pimp Trizkit

J'ai fait une solution qui fonctionne très bien pour moi:

function shadeColor(color, percent) {

    var R = parseInt(color.substring(1,3),16);
    var G = parseInt(color.substring(3,5),16);
    var B = parseInt(color.substring(5,7),16);

    R = parseInt(R * (100 + percent) / 100);
    G = parseInt(G * (100 + percent) / 100);
    B = parseInt(B * (100 + percent) / 100);

    R = (R<255)?R:255;  
    G = (G<255)?G:255;  
    B = (B<255)?B:255;  

    var RR = ((R.toString(16).length==1)?"0"+R.toString(16):R.toString(16));
    var GG = ((G.toString(16).length==1)?"0"+G.toString(16):G.toString(16));
    var BB = ((B.toString(16).length==1)?"0"+B.toString(16):B.toString(16));

    return "#"+RR+GG+BB;
}

Exemple Lighten:

shadeColor("#63C6FF",40);

Exemple assombrir:

shadeColor("#63C6FF",-40);
97
Pablo

C'est ce que j'ai utilisé en fonction de votre fonction. Je préfère utiliser les étapes plutôt que le pourcentage car c'est plus intuitif pour moi.

Par exemple, 20% d'une valeur bleue de 200 sont très différents de 20% d'une valeur bleue de 40.

Quoi qu'il en soit, voici ma modification, merci pour votre fonction d'origine.

function adjustBrightness(col, amt) {

    var usePound = false;

    if (col[0] == "#") {
        col = col.slice(1);
        usePound = true;
    }

    var R = parseInt(col.substring(0,2),16);
    var G = parseInt(col.substring(2,4),16);
    var B = parseInt(col.substring(4,6),16);

    // to make the colour less bright than the input
    // change the following three "+" symbols to "-"
    R = R + amt;
    G = G + amt;
    B = B + amt;

    if (R > 255) R = 255;
    else if (R < 0) R = 0;

    if (G > 255) G = 255;
    else if (G < 0) G = 0;

    if (B > 255) B = 255;
    else if (B < 0) B = 0;

    var RR = ((R.toString(16).length==1)?"0"+R.toString(16):R.toString(16));
    var GG = ((G.toString(16).length==1)?"0"+G.toString(16):G.toString(16));
    var BB = ((B.toString(16).length==1)?"0"+B.toString(16):B.toString(16));

    return (usePound?"#":"") + RR + GG + BB;

}
4
Eric Sloan

avez-vous pensé à une conversion rgb> hsl? alors il suffit de déplacer la luminosité de haut en bas? c'est comme ça que j'irais.

Un rapide coup d'œil à certains algorithmes m'a fourni les sites suivants.

PHP: http://serennu.com/colour/rgbtohsl.php

Javascript: http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript

ÉDITEZ le lien ci-dessus n'est plus valide. Vous pouvez afficher git hub pour le source de la page ou le Gist

Alternativement, un autre StackOverflow question pourrait être un bon endroit pour regarder.


Même si ce n’est pas le bon choix pour le PO, voici une approximation du code que j’avais suggéré à l’origine. (En supposant que vous ayez des fonctions de conversion rgb/hsl)

var SHADE_SHIFT_AMOUNT = 0.1; 

function lightenShade(colorValue)
{
    if(colorValue && colorValue.length >= 6)
    {
        var redValue = parseInt(colorValue.slice(-6,-4), 16);
        var greenValue = parseInt(colorValue.slice(-4,-2), 16);
        var blueValue = parseInt(colorValue.slice(-2), 16);

        var hsl = rgbToHsl(redValue, greenValue, blueValue);
        hsl[2]= Math.min(hsl[2] + SHADE_SHIFT_AMOUNT, 1);
        var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
        return "#" + rgb[0].toString(16) + rgb[1].toString(16) + rgb[2].toString(16);
    }
    return null;
}

function darkenShade(colorValue)
{
    if(colorValue && colorValue.length >= 6)
    {
        var redValue = parseInt(colorValue.slice(-6,-4), 16);
        var greenValue = parseInt(colorValue.slice(-4,-2), 16);
        var blueValue = parseInt(colorValue.slice(-2), 16);

        var hsl = rgbToHsl(redValue, greenValue, blueValue);
        hsl[2]= Math.max(hsl[2] - SHADE_SHIFT_AMOUNT, 0);
        var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
        return "#" + rgb[0].toString(16) + rgb[1].toString(16) + rgb[2].toString(16);
    }
    return null;
}

Cela suppose:

  1. Vous avez les fonctions hslToRgb et rgbToHsl.
  2. Le paramètre colorValue est une chaîne sous la forme # RRGGBB

Bien que si nous parlons de CSS, il existe une syntaxe pour spécifier hsl/hsla pour IE9/Chrome/Firefox.

4
James Khoury

J'ai essayé votre fonction et il y avait un petit bug: Si une valeur finale de 'r' est un chiffre, le résultat est comme: 'a0a0a' lorsque la bonne valeur est '0a0a0a', par exemple. Je viens de le réparer rapidement en ajoutant ceci à la place de votre retour:

var rStr = (r.toString(16).length < 2)?'0'+r.toString(16):r.toString(16);
var gStr = (g.toString(16).length < 2)?'0'+g.toString(16):g.toString(16);
var bStr = (b.toString(16).length < 2)?'0'+b.toString(16):b.toString(16);

return (usePound?"#":"") + rStr + gStr + bStr;

Peut-être que ce n'est pas si gentil mais ça fait le travail. Super fonction, BTW. Juste ce dont j'avais besoin. :)

4
Cool Acid

Voici une doublure super simple basée sur la réponse d'Eric

function adjust(color, amount) {
    return '#' + color.replace(/^#/, '').replace(/../g, color => ('0'+Math.min(255, Math.max(0, parseInt(color, 16) + amount)).toString(16)).substr(-2));
}

Exemples:

adjust('#ffffff', -20) => "#ebebeb"
adjust('000000', 20) => "#141414"
2
supersan

Je voulais changer une couleur en un niveau de luminosité spécifique - quelle que soit la luminosité de la couleur auparavant - voici une simple fonction JS qui semble bien fonctionner, même si je suis sûre qu'elle pourrait être plus courte

function setLightPercentage(col: any, p: number) {
    const R = parseInt(col.substring(1, 3), 16);
    const G = parseInt(col.substring(3, 5), 16);
    const B = parseInt(col.substring(5, 7), 16);
    const curr_total_dark = (255 * 3) - (R + G + B);

    // calculate how much of the current darkness comes from the different channels
    const RR = ((255 - R) / curr_total_dark);
    const GR = ((255 - G) / curr_total_dark);
    const BR = ((255 - B) / curr_total_dark);

    // calculate how much darkness there should be in the new color
    const new_total_dark = ((255 - 255 * (p / 100)) * 3);

    // make the new channels contain the same % of available dark as the old ones did
    const NR = 255 - Math.round(RR * new_total_dark);
    const NG = 255 - Math.round(GR * new_total_dark);
    const NB = 255 - Math.round(BR * new_total_dark);

    const RO = ((NR.toString(16).length === 1) ? "0" + NR.toString(16) : NR.toString(16));
    const GO = ((NG.toString(16).length === 1) ? "0" + NG.toString(16) : NG.toString(16));
    const BO = ((NB.toString(16).length === 1) ? "0" + NB.toString(16) : NB.toString(16));

    return "#" + RO + GO + BO;}
2

La méthode suivante vous permettra d'éclaircir ou d'assombrir la valeur d'exposition d'une chaîne de couleur hexadécimale (Hex):

private static string GetHexFromRGB(byte r, byte g, byte b, double exposure)
{
    exposure = Math.Max(Math.Min(exposure, 1.0), -1.0);
    if (exposure >= 0)
    {
        return "#"
            + ((byte)(r + ((byte.MaxValue - r) * exposure))).ToString("X2")
            + ((byte)(g + ((byte.MaxValue - g) * exposure))).ToString("X2")
            + ((byte)(b + ((byte.MaxValue - b) * exposure))).ToString("X2");
    }
    else
    {
        return "#"
            + ((byte)(r + (r * exposure))).ToString("X2")
            + ((byte)(g + (g * exposure))).ToString("X2")
            + ((byte)(b + (b * exposure))).ToString("X2");
    }

}

Pour la dernière valeur de paramètre dans GetHexFromRGB (), transmettez une valeur double quelque part entre -1 et 1 (-1 est noir, 0 est inchangé, 1 est blanc):

// split color (#e04006) into three strings
var r = Convert.ToByte("e0", 16);
var g = Convert.ToByte("40", 16);
var b = Convert.ToByte("06", 16);

GetHexFromRGB(r, g, b, 0.25);  // Lighten by 25%;
1
Jason Williams

C # Version ... notez que je reçois des chaînes de couleur dans ce format # FF12AE34 et que je dois découper le #FF.

    private string GetSmartShadeColorByBase(string s, float percent)
    {
        if (string.IsNullOrEmpty(s))
            return "";
        var r = s.Substring(3, 2);
        int rInt = int.Parse(r, NumberStyles.HexNumber);
        var g = s.Substring(5, 2);
        int gInt = int.Parse(g, NumberStyles.HexNumber);
        var b = s.Substring(7, 2);
        int bInt = int.Parse(b, NumberStyles.HexNumber);

        var t = percent < 0 ? 0 : 255;
        var p = percent < 0 ? percent*-1 : percent;

        int newR = Convert.ToInt32(Math.Round((t - rInt) * p) + rInt);
        var newG = Convert.ToInt32(Math.Round((t - gInt) * p) + gInt);
        var newB = Convert.ToInt32(Math.Round((t - bInt) * p) + bInt);

        return String.Format("#{0:X2}{1:X2}{2:X2}", newR, newG, newB);
    }
1
user1618171

J'ai créé un portage de l'excellente bibliothèque xcolor pour supprimer sa dépendance à jQuery. Il y a une tonne de fonctions, y compris éclaircir et assombrir les couleurs.

En réalité, la conversion hexadécimale en RVB est une fonction totalement distincte des couleurs éclaircies ou assombries. Gardez les choses DRY s'il vous plaît. Dans tous les cas, une fois que vous avez une couleur RVB, vous pouvez simplement ajouter la différence entre le niveau de lumière souhaité et le niveau de lumière que vous avez pour chacune des valeurs RVB:

var lightness = function(level) {
    if(level === undefined) {
        return Math.max(this.g,this.r,this.b)
    } else {
        var roundedLevel = Math.round(level) // fractions won't work here
        var levelChange = roundedLevel - this.lightness()

        var r = Math.max(0,this.r+levelChange)
        var g = Math.max(0,this.g+levelChange)
        var b = Math.max(0,this.b+levelChange)

        if(r > 0xff) r = 0xff
        if(g > 0xff) g = 0xff
        if(b > 0xff) b = 0xff

        return xolor({r: r, g: g, b: b})
    }
}

var lighter = function(amount) {
    return this.lightness(this.lightness()+amount)
}

Voir https://github.com/fresheneesz/xolor pour plus d'informations sur le source.

0
B T

Comment faire pour colorer une nuance en PHP?

<?php
function shadeColor ($color='#cccccc', $percent=-25) {

  $color = Str_Replace("#",Null,$color);

  $r = Hexdec(Substr($color,0,2));
  $g = Hexdec(Substr($color,2,2));
  $b = Hexdec(Substr($color,4,2));

  $r = (Int)($r*(100+$percent)/100);
  $g = (Int)($g*(100+$percent)/100);
  $b = (Int)($b*(100+$percent)/100);

  $r = Trim(Dechex(($r<255)?$r:255));  
  $g = Trim(Dechex(($g<255)?$g:255));  
  $b = Trim(Dechex(($b<255)?$b:255));

  $r = ((Strlen($r)==1)?"0{$r}":$r);
  $g = ((Strlen($g)==1)?"0{$g}":$g);
  $b = ((Strlen($b)==1)?"0{$b}":$b);

  return (String)("#{$r}{$g}{$b}");
}

echo shadeColor(); // #999999
0
jsebestyan

Je veux depuis longtemps pouvoir produire des teintes/nuances de couleurs, voici ma solution JavaScript:

const varyHue = function (hueIn, pcIn) {
    const truncate = function (valIn) {
        if (valIn > 255) {
            valIn = 255;
        } else if (valIn < 0)  {
            valIn = 0;
        }
        return valIn;
    };

    let red   = parseInt(hueIn.substring(0, 2), 16);
    let green = parseInt(hueIn.substring(2, 4), 16);
    let blue  = parseInt(hueIn.substring(4, 6), 16);
    let pc    = parseInt(pcIn, 10);    //shade positive, tint negative
    let max   = 0;
    let dif   = 0;

    max = red;

    if (pc < 0) {    //tint: make lighter
        if (green < max) {
            max = green;
        }

        if (blue < max) {
            max = blue;
        }

        dif = parseInt(((Math.abs(pc) / 100) * (255 - max)), 10);

        return leftPad(((truncate(red + dif)).toString(16)), '0', 2)  + leftPad(((truncate(green + dif)).toString(16)), '0', 2) + leftPad(((truncate(blue + dif)).toString(16)), '0', 2);
    } else {    //shade: make darker
        if (green > max) {
            max = green;
        }

        if (blue > max) {
            max = blue;
        }

        dif = parseInt(((pc / 100) * max), 10);

        return leftPad(((truncate(red - dif)).toString(16)), '0', 2)  + leftPad(((truncate(green - dif)).toString(16)), '0', 2) + leftPad(((truncate(blue - dif)).toString(16)), '0', 2);
    }
};
0
user2655360