Programowo rozjaśnij lub przyciemnij kolor szesnastkowy (lub rgb i mieszaj kolory)

Oto funkcja, nad którą pracowałem, aby programowo rozjaśnić lub przyciemnić kolor sześciokątny o określoną ilość. Wystarczy przekazać ciąg znaków jak {[4] } dla koloru (col) i base10 integer (amt) dla ilości rozjaśnić lub przyciemnić. Aby przyciemnić, podaj liczbę ujemną (tj. -20).

Powodem, dla którego to zrobiłem, było to, że wszystkie rozwiązania, które znalazłem, jak dotąd wydawały się nadmiernie komplikować problem. Miałem przeczucie, że da się to zrobić za pomocą kilku linijek kodu. Proszę. daj mi znać, jeśli znajdziesz jakieś problemy lub masz jakieś poprawki, które przyspieszą to.

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

Do użytku deweloperskiego jest tu łatwiejsza do odczytania wersja:

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);
}

I wreszcie Wersja do obsługi kolorów, które mogą (lub nie) mieć " # " na początku. Plus dostosowanie do niewłaściwych wartości kolorów:

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, więc teraz to nie tylko kilka linijek, ale wydaje się znacznie prostsze i jeśli nie używasz " # " i nie musisz sprawdzać kolorów poza zasięgiem, jest to tylko kilka linijek.

Jeśli nie używasz"#", możesz po prostu dodać go w kodzie:

var myColor = "3F6D2A";
myColor = LightenDarkenColor(myColor,10);
thePlaceTheColorIsUsed = ("#" + myColor);
Moje główne pytanie brzmi: Czy mam rację? Czy nie obejmuje to pewnych (normalnych) sytuacji?
Author: Pimp Trizkit, 2011-04-06

11 answers

TL; DR? --chcesz prostego rozjaśnienia/przyciemnienia (cieniowania)? Przejdź do wersji 2, Wybierz tę Dla RGB lub Hex. -- Chcesz w pełni funkcjonalny shader / blender / konwerter z errorcheck I alpha i 3 cyfr hex? Użyj wersji 3 w pobliżu dna.

Graj z wersją 3.1: Jsfiddle > shadeBlendConvert przykład

Wersja 3.1 na GitHub: Goto GitHub > PJs > pSBC


Po kilku rozmyślaniach... Postanowiłem odpowiedzieć na własne pytanie. Rok i pół później. To była naprawdę przygoda z pomysłami od kilku pomocnych użytkowników i dziękuję wszystkim! Ten jest dla drużyny! Choć niekoniecznie takiej odpowiedzi Szukałem. Bo jeśli to, co mówi James Khoury jest prawdą, to nie ma prawdziwej matematyki szesnastkowej w javascript, muszę użyć dziesiętnych, ta podwójna konwersja jest konieczna. Jeśli przyjmiemy to założenie, to jest to prawdopodobnie najszybszy sposób, jaki widziałem (lub mogę myśleć), aby rozjaśnić (dodać biały) lub przyciemnić (dodać czarny) dowolny Kolor RBG w procentach. Odpowiada również na kwestie, o których Cool Acid wspomniał w odpowiedzi na to pytanie (pads 0s). Ale ta wersja wywołuje toString tylko raz. To również stanowi poza zakresem (wymusi 0 i 255 jako limity).

Ale uwaga, wejście koloru musi mieć dokładnie 7 znaków, jak #08a35c. (lub 6 Jeśli używasz wersji top)

Dzięki Pablo za inspirację i pomysł na wykorzystanie procentu. W tym celu zachowam nazwę funkcji tak samo! lol! Jednakże, ten jest inny, ponieważ normalizuje procent do 255 i tym samym dodając tę samą ilość do każdego koloru (więcej białego). Jeśli przejdziesz 100 za percent, twój kolor będzie czysty biały. Jeśli zdasz w 0 za percent, nic się nie stanie. Jeśli przejdziesz w 1 dla percent, doda 3 odcienie do wszystkich kolorów (2,55 odcieni na 1%, zaokrąglone). Więc naprawdę przechodzi w procentach białego (lub czarny, użyj negatyw). Dlatego ta wersja pozwala na rozjaśnienie czystej Czerwieni (FF0000), na przykład.

I wykorzystałem również wgląd z odpowiedzi Keitha Mashintera na to pytanie: Jak przekonwertować dziesiętne na szesnastkowe w JavaScript?

Usunąłem zbędny nawias. (jak w Double ternary statement i w crafting G) nie jestem pewien, czy to spowoduje bałagan z pierwszeństwem operatora w niektórych środowiskach. Testowany dobrze w Firefoksie.
function shadeColor1(color, percent) {  // deprecated. See below.
    var num = parseInt(color,16),
    amt = Math.round(2.55 * percent),
    R = (num >> 16) + amt,
    G = (num >> 8 & 0x00FF) + amt,
    B = (num & 0x0000FF) + amt;
    return (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (G<255?G<1?0:G:255)*0x100 + (B<255?B<1?0:B:255)).toString(16).slice(1);
}

Lub, jeśli chcesz, aby obsługiwał"#":

function shadeColor1(color, percent) {  // deprecated. See below.
    var num = parseInt(color.slice(1),16), amt = Math.round(2.55 * percent), R = (num >> 16) + amt, G = (num >> 8 & 0x00FF) + amt, B = (num & 0x0000FF) + amt;
    return "#" + (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (G<255?G<1?0:G:255)*0x100 + (B<255?B<1?0:B:255)).toString(16).slice(1);
}

Jak to jest dla dwóch linijek kodu?

EDIT: Fix B g swap goof. Dzięki svachalek!


-- UPDATE-Version 2 with Blending -- Nieco ponad rok później, znowu, i nadal trwa. Ale tym razem myślę, że już po wszystkim. Zwracając uwagę na problemy wymienione na temat nie używania HSL do prawidłowego rozjaśnienia koloru. Istnieje technika, która eliminuje większość tej niedokładności bez konieczności konwersji do HSL. Głównym problemem jest to, że kanał kolorów będzie w pełni nasycony przed resztą koloru. Powoduje zmianę barwy po tym punkcie. I znalazłem te pytania tutaj, tutaj i tutaj, które wprowadziły mnie na właściwe tory. Post Marka Ransoma pokazał mi różnicę, a post Keitha pokazał mi drogę. Lerp jest wybawcą. Jest to to samo, co mieszanie kolorów, więc stworzyłem również funkcję blendColors.

TL; DR - dla prostego rozjaśnienia / przyciemnienia użyj poniższej funkcji shadeColor2. Lub jego odpowiednikiem RGB shadeRGBColor poniżej i daj mi jeden głos. Ale jeśli chcesz dowolnych i / lub wszystkich smakołyków. Takie jak możliwość korzystania zarówno z kolorów RGB, jak i Hex, Sprawdzanie błędów, dekodowanie szesnastkowe 3, mieszanie, kanały alfa i konwersje RGB2Hex / Hex2RGB. Następnie przejdź do wersji 3 dla shadeBlendConvert, aby uzyskać wszystkie dzwonki i gwizdki i dać mi dwa głosy. Następnie możesz usunąć kilka linii, aby usunąć niektóre z tych funkcji, jeśli chcesz. I dostajesz głos, jeśli pamiętasz, że Wersja 1 shadeColor1 powyżej jest przestarzała dla wszystkich zastosowań.


Więc, bez dalszych ceregieli:

-Wersja 2 Hex -

function shadeColor2(color, percent) {   
    var f=parseInt(color.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF;
    return "#"+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1);
}

function blendColors(c0, c1, p) {
    var f=parseInt(c0.slice(1),16),t=parseInt(c1.slice(1),16),R1=f>>16,G1=f>>8&0x00FF,B1=f&0x0000FF,R2=t>>16,G2=t>>8&0x00FF,B2=t&0x0000FF;
    return "#"+(0x1000000+(Math.round((R2-R1)*p)+R1)*0x10000+(Math.round((G2-G1)*p)+G1)*0x100+(Math.round((B2-B1)*p)+B1)).toString(16).slice(1);
}

Dalej ado:

Nie ma sprawdzania błędów, więc przekazywane wartości, które są poza zakresem, spowodują nieoczekiwane wyniki. Ponadto, wejście koloru musi mieć dokładnie 7 znaków, jak #08a35c. Ale wszystkie inne gadżety są nadal tutaj, takie jak output range capping (wyjścia 00-FF), padding (0a), uchwyty # i użyteczne dla jednolitych kolorów, jak #FF0000.

[73]}ta nowa wersja shadeColor przyjmuje w float dla drugiego parametru. Dla shadeColor2 poprawny zakres dla drugiego (procentowego) parametru to -1.0 do 1.0.

I dla blendColors poprawny zakres dla trzeciego (procentowego) parametru to 0.0 do 1.0, negatywy nie są tu dozwolone.

Ta nowa wersja nie przyjmuje już procentu czystej bieli, jak stara wersja. Jego biorąc w procentach odległość od koloru nadanego do czystej bieli. W starej wersji łatwo było nasycić kolor, a w rezultacie, wiele kolorów obliczałoby czystą biel przy użyciu sporego procentu. Ten nowy sposób, oblicza się tylko do czystej bieli, jeśli przejdziesz 1.0, lub czystej czerni, użyj -1.0.

Wywołanie blendColors(color, "#FFFFFF", 0.5) jest tym samym co shadeColor2(color,0.5). A także blendColors(color,"#000000", 0.5) jest tym samym co shadeColor2(color,-0.5). Tylko trochę wolniej.

shadeColor2 jest wolniejszy niż shadeColor1, ale nie o zauważalną ilość. (Czekaj, to samo zaprzeczające stwierdzenie!)

Uzyskaną dokładność można zobaczyć tutaj:

-- Wersja 2 RGB --

function shadeRGBColor(color, percent) {
    var f=color.split(","),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=parseInt(f[0].slice(4)),G=parseInt(f[1]),B=parseInt(f[2]);
    return "rgb("+(Math.round((t-R)*p)+R)+","+(Math.round((t-G)*p)+G)+","+(Math.round((t-B)*p)+B)+")";
}

function blendRGBColors(c0, c1, p) {
    var f=c0.split(","),t=c1.split(","),R=parseInt(f[0].slice(4)),G=parseInt(f[1]),B=parseInt(f[2]);
    return "rgb("+(Math.round((parseInt(t[0].slice(4))-R)*p)+R)+","+(Math.round((parseInt(t[1])-G)*p)+G)+","+(Math.round((parseInt(t[2])-B)*p)+B)+")";
}

Zastosowania:

var color1 = "rbg(63,131,163)";
var lighterColor = shadeRGBColor(color1, 0.5);  //  rgb(159,193,209)
var darkerColor = shadeRGBColor(color1, -0.25); //  rgb(47,98,122)

var color2 = "rbg(244,128,0)";
var blend1 = blendRGBColors(color1, color2, 0.75);  //  rgb(199,129,41)
var blend2 = blendRGBColors(color2, color1, 0.62);  //  rgb(132,130,101)

-- Wersja 2 Uniwersalna A --

function shade(color, percent){
    if (color.length > 7 ) return shadeRGBColor(color,percent);
    else return shadeColor2(color,percent);
}

function blend(color1, color2, percent){
    if (color1.length > 7) return blendRGBColors(color1,color2,percent);
    else return blendColors(color1,color2,percent);
}

Użycie:

var color1 = shade("rbg(63,131,163)", 0.5);
var color2 = shade("#3f83a3", 0.5);
var color3 = blend("rbg(63,131,163)", "rbg(244,128,0)", 0.5);
var color4 = blend("#3f83a3", "#f48000", 0.5);

-- Wersja 2 Uniwersalna B --

Ok, w porządku! Popularność tej odpowiedzi sprawiła, że pomyślałem, że mógłbym zrobić znacznie lepszą uniwersalną wersję tego. Więc proszę bardzo! Ta wersja jest All-In-One funkcja kopiuj/wklej-stanie shader / blender zarówno dla kolorów RGB I Hex. Ta tak naprawdę nie różni się od innych wersji Uni podane powyżej. Z wyjątkiem tego, że jest o wiele mniejszy i tylko jedna funkcja do wklejania i używania. Myślę, że rozmiar wzrósł z około 1592 znaków do 557 znaków, jeśli skompresujesz go w jedną linię. oczywiście, jeśli nie musisz używać go zamiennie między RGB i Hex, to i tak nie potrzebujesz uniwersalnej wersji takiej jak ta, lol. po prostu użyj jednej z znacznie mniejszych i szybszych wersji powyżej; odpowiednie dla twojego schematu kolorów. Idziemy dalej... W pewnym sensie jest trochę szybciej, w niektórych sposoby jest trochę wolniej. Nie zrobiłem żadnej końcowej analizy testu prędkości. Istnieją dwie różnice w użytkowaniu: po pierwsze, procent jest teraz pierwszym parametrem funkcji, a nie ostatnim. Po drugie, podczas mieszania można użyć liczb ujemnych. Po prostu zostaną przekonwertowane na liczby dodatnie.

No more ado:

function shadeBlend(p,c0,c1) {
    var n=p<0?p*-1:p,u=Math.round,w=parseInt;
    if(c0.length>7){
        var f=c0.split(","),t=(c1?c1:p<0?"rgb(0,0,0)":"rgb(255,255,255)").split(","),R=w(f[0].slice(4)),G=w(f[1]),B=w(f[2]);
        return "rgb("+(u((w(t[0].slice(4))-R)*n)+R)+","+(u((w(t[1])-G)*n)+G)+","+(u((w(t[2])-B)*n)+B)+")"
    }else{
        var f=w(c0.slice(1),16),t=w((c1?c1:p<0?"#000000":"#FFFFFF").slice(1),16),R1=f>>16,G1=f>>8&0x00FF,B1=f&0x0000FF;
        return "#"+(0x1000000+(u(((t>>16)-R1)*n)+R1)*0x10000+(u(((t>>8&0x00FF)-G1)*n)+G1)*0x100+(u(((t&0x0000FF)-B1)*n)+B1)).toString(16).slice(1)
    }
}

Użycie:

var color1 = "#FF343B";
var color2 = "#343BFF";
var color3 = "rgb(234,47,120)";
var color4 = "rgb(120,99,248)";
var shadedcolor1 = shadeBlend(0.75,color1);
var shadedcolor3 = shadeBlend(-0.5,color3);
var blendedcolor1 = shadeBlend(0.333,color1,color2);
var blendedcolor34 = shadeBlend(-0.8,color3,color4); // Same as using 0.8

teraz może być idealnie! ;) @ Mevin

* V2 inne języki *

-- Rozszerzenie Swift-RGB (by Matej Ukmar) --

extension UIColor {
    func shadeColor(factor: CGFloat) -> UIColor {
        var r: CGFloat = 0
        var g: CGFloat = 0
        var b: CGFloat = 0
        var a: CGFloat = 0
        var t: CGFloat = factor < 0 ? 0 : 1
        var p: CGFloat = factor < 0 ? -factor : factor
        getRed(&r, green: &g, blue: &b, alpha: &a)
        r = (t-r)*p+r
        g = (t-g)*p+g
        b = (t-b)*p+b
        return UIColor(red: r, green: g, blue: b, alpha: a)
    }
}

-- wersja PHP-HEX (by Kevin M) --

function shadeColor2($color, $percent) {
    $color = str_replace("#", "", $color);
    $t=$percent<0?0:255;
    $p=$percent<0?$percent*-1:$percent;
    $RGB = str_split($color, 2);
    $R=hexdec($RGB[0]);
    $G=hexdec($RGB[1]);
    $B=hexdec($RGB[2]);
    return '#'.substr(dechex(0x1000000+(round(($t-$R)*$p)+$R)*0x10000+(round(($t-$G)*$p)+$G‌​)*0x100+(round(($t-$B)*$p)+$B)),1);
}


-- UPDATE -- Version 3.1 Universal --

(to zostało dodane do mojej biblioteki na GitHub)

Za kilka miesięcy minie kolejny rok od ostatniej uniwersalnej wersji. Więc... dziękisricks ' S wnikliwy komentarz. Postanowiłem zabrać go do kolejny poziom. To już nie jest demon prędkości dwóch linii, jak to się zaczęło, lol. Ale za to, co robi, jest dość szybki i mały. Jego około 1600 bajtów. Jeśli usuniesz błąd i usuniesz dekodowanie cyfr 3, możesz go obniżyć do około 1200 bajtów i szybciej. To jest dużo mocy w około K. wyobraź sobie, możesz załadować to na Commodore64 i nadal mieć miejsce dla 50 Więcej z nich! (Pomijając fakt, że silnik JavaScript jest większy niż 63k)

Najwyraźniej było więcej adoing do zrobienia:

const shadeBlendConvert = function (p, from, to) {
    if(typeof(p)!="number"||p<-1||p>1||typeof(from)!="string"||(from[0]!='r'&&from[0]!='#')||(to&&typeof(to)!="string"))return null; //ErrorCheck
    if(!this.sbcRip)this.sbcRip=(d)=>{
        let l=d.length,RGB={};
        if(l>9){
            d=d.split(",");
            if(d.length<3||d.length>4)return null;//ErrorCheck
            RGB[0]=i(d[0].split("(")[1]),RGB[1]=i(d[1]),RGB[2]=i(d[2]),RGB[3]=d[3]?parseFloat(d[3]):-1;
        }else{
            if(l==8||l==6||l<4)return null; //ErrorCheck
            if(l<6)d="#"+d[1]+d[1]+d[2]+d[2]+d[3]+d[3]+(l>4?d[4]+""+d[4]:""); //3 or 4 digit
            d=i(d.slice(1),16),RGB[0]=d>>16&255,RGB[1]=d>>8&255,RGB[2]=d&255,RGB[3]=-1;
            if(l==9||l==5)RGB[3]=r((RGB[2]/255)*10000)/10000,RGB[2]=RGB[1],RGB[1]=RGB[0],RGB[0]=d>>24&255;
        }
    return RGB;}
    var i=parseInt,r=Math.round,h=from.length>9,h=typeof(to)=="string"?to.length>9?true:to=="c"?!h:false:h,b=p<0,p=b?p*-1:p,to=to&&to!="c"?to:b?"#000000":"#FFFFFF",f=this.sbcRip(from),t=this.sbcRip(to);
    if(!f||!t)return null; //ErrorCheck
    if(h)return "rgb"+(f[3]>-1||t[3]>-1?"a(":"(")+r((t[0]-f[0])*p+f[0])+","+r((t[1]-f[1])*p+f[1])+","+r((t[2]-f[2])*p+f[2])+(f[3]<0&&t[3]<0?")":","+(f[3]>-1&&t[3]>-1?r(((t[3]-f[3])*p+f[3])*10000)/10000:t[3]<0?f[3]:t[3])+")");
    else return "#"+(0x100000000+r((t[0]-f[0])*p+f[0])*0x1000000+r((t[1]-f[1])*p+f[1])*0x10000+r((t[2]-f[2])*p+f[2])*0x100+(f[3]>-1&&t[3]>-1?r(((t[3]-f[3])*p+f[3])*255):t[3]>-1?r(t[3]*255):f[3]>-1?r(f[3]*255):255)).toString(16).slice(1,f[3]>-1||t[3]>-1?undefined:-2);
}

Graj z wersją 3.1: Jsfiddle > shadeBlendConvert przykład

Podstawowa matematyka tej wersji jest taka sama jak poprzednio. Ale zrobiłem poważną refaktoryzację. Pozwoliło to na znacznie większą funkcjonalność i kontrolę. Teraz z natury konwertuje RGB2Hex i Hex2RGB.

Wszystkie stare funkcje z V2 powyżej powinny nadal być tutaj. Próbowałem przetestować to wszystko, proszę o komentarz, jeśli znajdziesz coś złego. Anyway, oto nowe funkcje:

  • akceptuje 3-cyfrowe (lub 4-cyfrowe) kody kolorów HEX, w postaci #RGB (lub #ARGB). To je rozszerzy. usuń linię oznaczoną //3 digit, aby usunąć tę funkcję.
  • akceptuje i łączy kanały Alfa. Jeśli kolor from lub kolor to ma kanał alfa, to wynik będzie miał kanał alfa. Jeśli oba kolory mają kanał alfa, wynikiem będzie połączenie dwóch kanałów alfa z podaną wartością procentową (tak, jakby to był normalny kanał koloru). Jeśli tylko jeden z dwóch kolorów ma kanał alfa, alfa ta zostanie po prostu przekazana do wyniku. Pozwala to na mieszanie / cieniowanie przezroczystego koloru przy zachowaniu przezroczystego poziomu. Jeśli poziom przezroczysty również powinien się mieszać, upewnij się, że oba kolory mają Alfy. Cieniowanie przechodzi przez kanał alfa, jeśli chcesz, aby podstawowe cieniowanie łączyło również kanał alfa, użyj rgb(0,0,0,1) lub rgb(255,255,255,1) jako koloru to (lub ich szesnastki odpowiedniki). W przypadku kolorów RGB wynikowy kanał alfa zostanie zaokrąglony do 4 miejsc po przecinku.
  • konwersje RGB2Hex i Hex2RGB są teraz ukryte podczas mieszania. Kolor wyniku będzie zawsze w postaci koloru to, jeśli taki istnieje. Jeśli nie ma to koloru, podaj 'c' jako kolor to, a będzie on cieniowany i konwertowany. Jeśli wymagana jest tylko konwersja, podaj 0 jako wartość procentową.
  • funkcja wtórna jest dodawana do globalnej jako cóż. sbcRip może być przekazany kolor szesnastkowy lub RBG i zwraca obiekt zawierający informacje o tym kolorze. Its w formie: {0:R,1:G,2:B,3:A}. Gdzie R g i B mają zakres 0 do 255. A gdy nie ma Alfy: A jest -1. W przeciwnym razie: A ma zakres 0.0000 do 1.0000.
  • Dodano drobne Sprawdzanie błędów. To nie jest idealne. Nadal może się rozbić. Ale złapie kilka rzeczy. Zasadniczo, jeśli struktura jest niewłaściwa w jakiś sposób lub jeśli procent nie jest liczbą lub poza zakresem, zwróci null. Przykład: shadeBlendConvert(0.5,"salt") = null, gdzie według niego #salt jest prawidłowym kolorem. Usuń cztery linie oznaczone //ErrorCheck, aby usunąć tę funkcję.

Zastosowania:

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)";
let c;

// Shade (Lighten or Darken)
c = shadeBlendConvert ( 0.42, color1 ); // rgb(20,60,200) + [42% Lighter] => rgb(119,142,223)
c = shadeBlendConvert ( -0.4, color5 ); // #F3A + [40% Darker] => #991f66
c = shadeBlendConvert ( 0.42, color8 ); // rgba(200,60,20,0.98631) + [42% Lighter] => rgba(223,142,119,0.98631)
// Shade with Conversion (use "c" as your "to" color)
c = shadeBlendConvert ( 0.42, color2, "c" ); // rgba(20,60,200,0.67423) + [42% Lighter] + [Convert] => #778edfac
// RGB2Hex & Hex2RGB Conversion Only (set percentage to zero)
c = shadeBlendConvert ( 0, color6, "c" ); // #F3A9 + [Convert] => rgba(255,51,170,0.6)
// Blending
c = shadeBlendConvert ( -0.5, color2, color8 ); // rgba(20,60,200,0.67423) + rgba(200,60,20,0.98631) + [50% Blend] => rgba(110,60,110,0.8303)
c = shadeBlendConvert ( 0.7, color2, color7 ); // rgba(20,60,200,0.67423) + rgb(200,60,20) + [70% Blend] => rgba(146,60,74,0.67423)
c = shadeBlendConvert ( 0.25, color3, color7 ); // #67DAF0 + rgb(200,60,20) + [25% Blend] => rgb(127,179,185)
c = shadeBlendConvert ( 0.75, color7, color3 ); // rgb(200,60,20) + #67DAF0 + [75% Blend] => #7fb3b9
// Error Checking
c = shadeBlendConvert ( 0.42, "#FFBAA" ); // #FFBAA + [42% Lighter] => null  (Invalid Input Color)
c = shadeBlendConvert ( 42, color1, color5 ); // rgb(20,60,200) + #F3A + [4200% Blend] => null  (Invalid Percentage Range)
c = shadeBlendConvert ( 0.42, {} ); // [object Object] + [42% Lighter] => null  (Strings Only for Color)
c = shadeBlendConvert ( "42", color1 ); // rgb(20,60,200) + ["42"] => null  (Numbers Only for Percentage)
c = shadeBlendConvert ( 0.42, "salt" ); // salt + [42% Lighter] => null  (A Little Salt is No Good...)
// Error Check Fails (Some Errors are not Caught)
c = shadeBlendConvert ( 0.42, "#salt" ); // #salt + [42% Lighter] => #6b6b6b00  (...and a Pound of Salt is Jibberish)
// Ripping
c = sbcRip ( color4 ); // #5567DAF0 + [Rip] => [object Object] => {'0':85,'1':103,'2':218,'3':0.9412}
Waham się, czy to już koniec... jeszcze raz...

PT

--EDIT: przełączono wersję 3 Na let i funkcję strzałek oraz dodano this do wywołań sbcRip.

----======----

Tak mi wstyd! (i dziwię się, że nikt o tym nie wspomniał) najwyraźniej nie korzystam z kanałów alfa w moich własnych projektach... I... najwidoczniej zrobiłem straszne testy. Wersja 3 nie odczytywała ani nie zapisywała kolorów z kanałami Alfa poprawnie. Było kilka punktów, które albo po prostu się myliłem, albo nigdy się nie nauczyłem: {]}
  • Kolory Hex z alfą to #RGBA (nie #ARGB). Wersja 3 czytała i pisała to od tyłu.
  • kolory RGB z alphas musi być rgba(), a nie rgb(); wersja 3 nigdy nie wychodzi rgba().
  • Wersja 3 nie akceptowała rgba(), ale akceptowała Alfy w rgb(), co nie powinno się zdarzyć.

I właśnie teraz zastąpiłem wersję 3 wersją 3.1, gdzie te problemy są rozwiązywane. Nie umieściłem go tutaj jako osobnej funkcji, ponieważ stara wersja 3 powinna zostać usunięta z istnienia i zastąpiona tą. I tak właśnie zrobiłem. Wersja 3 powyżej jest w rzeczywistości wersją 3.1.

Wszystkie stare funkcje z góry są nadal tutaj z tymi aktualizacjami:

  • poprawnie odczytuje i zapisuje Kolory za pomocą kanałów alfa. Zarówno Hex, jak i RGB.
  • kolor to akceptuje teraz Kolor ciągu znaków lub falsy (który nadal może być undefined).
  • funkcja jest teraz stała.

... Cieszę się, że zawahałem się, żeby to powtórzyć. Oto jesteśmy, jakiś rok później ... wciąż ją doskonalę...

PT

 772
Author: Pimp Trizkit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-10 07:44:10

Zrobiłem rozwiązanie, które działa bardzo ładnie dla mnie:

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;
}

Przykład:

shadeColor("#63C6FF",40);

Przykład:

shadeColor("#63C6FF",-40);
 70
Author: Pablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-30 16:02:21

Próbowałem twojej funkcji i pojawił się mały błąd: jeśli jakaś końcowa wartość 'r' jest tylko 1 cyfrą, wynik pojawia się jak: 'a0a0a', gdy właściwa wartość to '0a0a0a', na przykład. Po prostu szybko to naprawiłem dodając To zamiast twojego powrotu:

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;

Może nie jest taki miły, ale robi robotę. Świetna funkcja, BTW. Właśnie tego potrzebowałem. :)

 4
Author: Cool Acid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-06 20:13:50

Czy myślałeś o konwersji rgb > hsl? więc po prostu przesuń jasność w górę iw dół? tak bym poszedł.

Szybkie szukanie niektórych algorytmów dało mi następujące strony.

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

EDIT powyższy link jest już nieaktualny. Możesz zobaczyć git hub dla źródła strony lub gist

Alternatywnie inne pytanie Stoskoverflow może być dobrym miejscem do szukania.


Mimo, że nie jest to właściwy wybór dla OP, poniżej znajduje się przybliżenie kodu, który pierwotnie sugerowałem. (Zakładając, że masz funkcje konwersji 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;
}

Zakłada się:

  1. masz Funkcje hslToRgb i rgbToHsl.
  2. parametr colorValue jest ciągiem znaków w postaci #RRGGBB

Chociaż jeśli mówimy o css, istnieje składnia do określenia hsl/hsla dla IE9/Chrome/Firefox.

 3
Author: James Khoury,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:36

Tego użyłem w oparciu o twoją funkcję. Wolę używać kroków ponad procent, ponieważ jest to bardziej intuicyjne dla mnie.

Na przykład 20% niebieskiej wartości 200 różni się znacznie od 20% niebieskiej wartości 40.

W każdym razie, oto moja modyfikacja, dzięki za oryginalną funkcję.

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;

}
 3
Author: Eric Sloan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-16 04:06:26

Poniższa metoda pozwoli na rozjaśnienie lub przyciemnienie wartości ekspozycji ciągu kolorów w systemie szesnastkowym (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");
    }

}

Dla ostatniej wartości parametru w GetHexFromRGB(), podaj podwójną wartość gdzieś pomiędzy -1 i 1 (-1 jest czarne, 0 jest niezmienione, 1 jest białe):

// 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%;
 2
Author: Jason Williams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-07 22:36:26

Chciałem zmienić kolor na określony poziom jasności-bez względu na to, jaka jasność była wcześniej-oto prosta funkcja JS, która wydaje się działać dobrze, chociaż jestem pewien, że może być krótsza

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
Author: Torbjörn Josefsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-07 10:37:42

Wersja C#... zauważ, że dostaję kolorowe ciągi w tym formacie #FF12AE34 i muszę wyciąć #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
Author: user1618171,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-23 20:14:19

Jak prosty odcień koloru w 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
Author: jsebestyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-17 19:15:50

Zrobiłem port doskonałej biblioteki xcolor, aby usunąć jej zależność od jQuery. Istnieje mnóstwo funkcji, w tym rozjaśnianie i ciemnienie kolorów.

Naprawdę, konwersja hex NA RGB jest całkowicie oddzielną funkcją od rozjaśniania lub przyciemniania kolorów. Trzymaj rzeczy suche, proszę. W każdym przypadku, gdy masz kolor RGB, możesz po prostu dodać różnicę między żądanym poziomem światła a poziomem światła do każdej z wartości RGB:

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

Zobacz https://github.com/fresheneesz/xolor Więcej informacji o źródle.

 0
Author: B T,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-17 02:52:06

Od dawna chciałem być w stanie produkować odcienie / odcienie kolorów, oto moje rozwiązanie 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
Author: user2655360,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-29 03:00:36