2009-11-02 32 views
46

Weiß jemand von Anfang an eine Javascript-Lösung zur Berechnung der Komplementärfarbe eines Hexadezimalwerts?JS-Funktion zur Berechnung der Komplementärfarbe?

Es gibt eine Reihe von Farbauswahlsammlungen und Palettengeneratoren im Internet, aber ich habe noch keine gesehen, die die Farbe live mit JS berechnen.

Ein ausführlicher Hinweis oder ein Schnipsel würde sehr geschätzt werden.

Antwort

51

Analysierte durch http://design.geckotribe.com/colorwheel/

// complement 
temprgb=thisrgb; 
temphsv=RGB2HSV(temprgb); 
temphsv.hue=HueShift(temphsv.hue,180.0); 
temprgb=HSV2RGB(temphsv); 

function RGB2HSV(rgb) { 
    hsv = new Object(); 
    max=max3(rgb.r,rgb.g,rgb.b); 
    dif=max-min3(rgb.r,rgb.g,rgb.b); 
    hsv.saturation=(max==0.0)?0:(100*dif/max); 
    if (hsv.saturation==0) hsv.hue=0; 
    else if (rgb.r==max) hsv.hue=60.0*(rgb.g-rgb.b)/dif; 
    else if (rgb.g==max) hsv.hue=120.0+60.0*(rgb.b-rgb.r)/dif; 
    else if (rgb.b==max) hsv.hue=240.0+60.0*(rgb.r-rgb.g)/dif; 
    if (hsv.hue<0.0) hsv.hue+=360.0; 
    hsv.value=Math.round(max*100/255); 
    hsv.hue=Math.round(hsv.hue); 
    hsv.saturation=Math.round(hsv.saturation); 
    return hsv; 
} 

// RGB2HSV and HSV2RGB are based on Color Match Remix [http://color.twysted.net/] 
// which is based on or copied from ColorMatch 5K [http://colormatch.dk/] 
function HSV2RGB(hsv) { 
    var rgb=new Object(); 
    if (hsv.saturation==0) { 
     rgb.r=rgb.g=rgb.b=Math.round(hsv.value*2.55); 
    } else { 
     hsv.hue/=60; 
     hsv.saturation/=100; 
     hsv.value/=100; 
     i=Math.floor(hsv.hue); 
     f=hsv.hue-i; 
     p=hsv.value*(1-hsv.saturation); 
     q=hsv.value*(1-hsv.saturation*f); 
     t=hsv.value*(1-hsv.saturation*(1-f)); 
     switch(i) { 
     case 0: rgb.r=hsv.value; rgb.g=t; rgb.b=p; break; 
     case 1: rgb.r=q; rgb.g=hsv.value; rgb.b=p; break; 
     case 2: rgb.r=p; rgb.g=hsv.value; rgb.b=t; break; 
     case 3: rgb.r=p; rgb.g=q; rgb.b=hsv.value; break; 
     case 4: rgb.r=t; rgb.g=p; rgb.b=hsv.value; break; 
     default: rgb.r=hsv.value; rgb.g=p; rgb.b=q; 
     } 
     rgb.r=Math.round(rgb.r*255); 
     rgb.g=Math.round(rgb.g*255); 
     rgb.b=Math.round(rgb.b*255); 
    } 
    return rgb; 
} 

//Adding HueShift via Jacob (see comments) 
function HueShift(h,s) { 
    h+=s; while (h>=360.0) h-=360.0; while (h<0.0) h+=360.0; return h; 
} 

//min max via Hairgami_Master (see comments) 
function min3(a,b,c) { 
    return (a<b)?((a<c)?a:c):((b<c)?b:c); 
} 
function max3(a,b,c) { 
    return (a>b)?((a>c)?a:c):((b>c)?b:c); 
} 
+0

Das tat es, danke! –

+6

Die magische HueShift (...) Funktion ist dies: Funktion HueShift (h, s) { \t h + = s; \t während (h> = 360,0) h- = 360,0; \t während (h <0,0) h + = 360,0; \t zurück h; } – Jacob

+0

Sie benötigen auch die Funktionen max3 und min3: –

21

finde ich, dass gut funktioniert das bitweise Komplement nehmen, und zwar schnell.

var color = 0x320ae3; 
var complement = 0xffffff^color; 

Ich bin nicht sicher, ob es eine perfekte Ergänzung ist im Sinne von „zusammen mischt, um eine 70% grau bilden“, jedoch ein 70% iges Grau ist „pure white“ in Bezug auf Farbe Timing im Film. Es kam mir in den Sinn, dass das XORing des RGB-Hex aus reinem Weiß eine gute erste Annäherung sein könnte. Sie können auch ein dunkles Grau ausprobieren, um zu sehen, wie das für Sie funktioniert.

Auch hier handelt es sich um eine schnelle Näherung, und ich kann nicht garantieren, dass sie genau stimmt.

Siehe https://github.com/alfl/textful/blob/master/app.js#L38 für meine Implementierung.

+9

Das funktioniert gut, außer wenn das Ergebnis immer 6 Zeichen lang sein soll. Ich schlage '('000000' + (('0xffffff'^'0x320ae3'). ToString (16))). Slice (-6);' – professormeowingtons

+0

Buzzzz: (falsch) Was wäre die entgegengesetzte Farbe von 0x7F7F7F? 0x808080! Das ist nicht sehr "entgegengesetzt". XOR mit 0x808080 wäre besser (Farbabstand ist dann immer die Hälfte) aber immer noch nicht "am besten". Die HSL-Methoden liefern die besten Ergebnisse. – geowar

17

Keine der anderen Funktionen hier ausgearbeitet die Box, also habe ich diese gemacht.

Es dauert einen Hex-Wert, wandelt sie in HSL, verschiebt sich der Farbton 180 Grad und wandelt zurück zu Hex

/* hexToComplimentary : Converts hex value to HSL, shifts 
* hue by 180 degrees and then converts hex, giving complimentary color 
* as a hex value 
* @param [String] hex : hex value 
* @return [String] : complimentary color as hex value 
*/ 
function hexToComplimentary(hex){ 

    // Convert hex to rgb 
    // Credit to Denis http://stackoverflow.com/a/36253499/4939630 
    var rgb = 'rgb(' + (hex = hex.replace('#', '')).match(new RegExp('(.{' + hex.length/3 + '})', 'g')).map(function(l) { return parseInt(hex.length%2 ? l+l : l, 16); }).join(',') + ')'; 

    // Get array of RGB values 
    rgb = rgb.replace(/[^\d,]/g, '').split(','); 

    var r = rgb[0], g = rgb[1], b = rgb[2]; 

    // Convert RGB to HSL 
    // Adapted from answer by 0x000f http://stackoverflow.com/a/34946092/4939630 
    r /= 255.0; 
    g /= 255.0; 
    b /= 255.0; 
    var max = Math.max(r, g, b); 
    var min = Math.min(r, g, b); 
    var h, s, l = (max + min)/2.0; 

    if(max == min) { 
     h = s = 0; //achromatic 
    } else { 
     var d = max - min; 
     s = (l > 0.5 ? d/(2.0 - max - min) : d/(max + min)); 

     if(max == r && g >= b) { 
      h = 1.0472 * (g - b)/d ; 
     } else if(max == r && g < b) { 
      h = 1.0472 * (g - b)/d + 6.2832; 
     } else if(max == g) { 
      h = 1.0472 * (b - r)/d + 2.0944; 
     } else if(max == b) { 
      h = 1.0472 * (r - g)/d + 4.1888; 
     } 
    } 

    h = h/6.2832 * 360.0 + 0; 

    // Shift hue to opposite side of wheel and convert to [0-1] value 
    h+= 180; 
    if (h > 360) { h -= 360; } 
    h /= 360; 

    // Convert h s and l values into r g and b values 
    // Adapted from answer by Mohsen http://stackoverflow.com/a/9493060/4939630 
    if(s === 0){ 
     r = g = b = l; // achromatic 
    } else { 
     var hue2rgb = function hue2rgb(p, q, t){ 
      if(t < 0) t += 1; 
      if(t > 1) t -= 1; 
      if(t < 1/6) return p + (q - p) * 6 * t; 
      if(t < 1/2) return q; 
      if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; 
      return p; 
     }; 

     var q = l < 0.5 ? l * (1 + s) : l + s - l * s; 
     var p = 2 * l - q; 

     r = hue2rgb(p, q, h + 1/3); 
     g = hue2rgb(p, q, h); 
     b = hue2rgb(p, q, h - 1/3); 
    } 

    r = Math.round(r * 255); 
    g = Math.round(g * 255); 
    b = Math.round(b * 255); 

    // Convert r b and g values to hex 
    rgb = b | (g << 8) | (r << 16); 
    return "#" + (0x1000000 | rgb).toString(16).substring(1); 
} 
+0

Das funktioniert super. Wie lange hast du gebraucht, um das zu schreiben? Ich war auf der Suche nach etwas, das dies eine Zeit lang tut, und stieß auch auf einige "out of the box" -Lösungen, die nicht funktionierten. – AlexanderGriffin

+1

Es dauerte eine Stunde oder so - ich habe nur einige stackoverflow Antworten (im Code gutgeschrieben) gepatcht. – Edd

Verwandte Themen