2012-03-16 13 views
34

piuttosto straight-forward, prendere giallo e bianco:Come calcolare a livello di codice il rapporto di contrasto tra due colori?

back_color = {r:255,g:255,b:255}; //white 
text_color = {r:255,g:255,b:0}; //yellow 

Quale legge della fisica sulla Terra di costanti universali di Dio, rende il fatto che il testo di colore giallo non può essere letto su sfondi bianchi ma il testo blu può?

Per il mio widget personalizzabile ho provato tutti i possibili modelli di colori per i quali ho trovato funzioni di conversione; nessuno dei due può dire che il verde può essere sul bianco e il giallo non può, sulla base di soli confronti numerici.

Ho guardato su Adsense (che è stato creato dal Budda di tutto Internet) e indovina cosa hanno fatto, hanno fatto i preset e calcoli della distanza delle celle di colore. Non posso farlo. I miei utenti hanno il diritto di scegliere anche le combinazioni più retiniche e antiestetiche, purché il testo possa ancora essere letto.

+0

modo che gli utenti possono scegliere due colori fintanto che sono essere letti contrastanti? – DanRedux

+0

Trovo questo interessante da un punto di vista tecnico, ma più pratico se i tuoi utenti hanno il "diritto" di scegliere qualsiasi colore perché ti interessa anche se può essere letto? Non sta a loro farlo bene? – nnnnnn

+0

@nnnnnn Non mi interessa davvero quali colori scelgono, possono mescolare quello che vogliono, ma mi interessa quanto sia leggibile la (c) 2012 Company Inc.. –

risposta

38

Secondo Wikipedia, quando si converte in scala di grigi la rappresentazione della luminanza "si devono ottenere i valori del rosso, del verde e del blu" e mescolarli nella proporzione successiva: R: 30% G: 59% B: 11%

Quindi il bianco avrà il 100% di luminanza e il giallo l'89%. Allo stesso tempo, il verde ha un minimo del 59%. L'11% è quasi quattro volte inferiore alla differenza del 41%!

E anche la calce (#00ff00) non va bene per la lettura di grandi quantità di testo.

IMHO per colori con contrasto buono la luminosità deve differire almeno per il 50%. E questa luminosità dovrebbe essere misurata come convertita in scala di grigi.

UPD: trovati di recente un comprehensive tool per quella sul web che a fine utilizza formula da w3 document valori soglia potrebbe essere preso da #1.4 Ecco un'implementazione per questa cosa più avanzato.

function luminanace(r, g, b) { 
    var a = [r, g, b].map(function (v) { 
     v /= 255; 
     return v <= 0.03928 
      ? v/12.92 
      : Math.pow((v + 0.055)/1.055, 2.4); 
    }); 
    return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722; 
} 
function contrast(rgb1, rgb2) { 
    return (luminanace(rgb1[0], rgb1[1], rgb1[2]) + 0.05) 
     /(luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05); 
} 
contrast([255, 255, 255], [255, 255, 0]); // 1.074 for yellow 
contrast([255, 255, 255], [0, 0, 255]); // 8.592 for blue 
// minimal recommended contrast ratio is 4.5, or 3 for larger font-sizes 
+1

+1 È vero. Nella vita reale: la conversione in scala di grigi per verificare la leggibilità dei disegni è un must (specialmente per i loghi). –

+0

Prenderò questa risposta come soluzione perché è la più completa e non posso scegliere due soluzioni; ma avrei scelto la risposta di HondaSuzukiShaolinShaorma perché fornisce un codice pronto all'uso. –

+0

Sì, mi piace anche la sua risposta =) – kirilloid

16

Ci sono vari modi per calcolare il contrasto, ma un modo comune è la formula:

brightness = (299*R + 587*G + 114*B)/1000 

A tale scopo, per entrambi i colori, e poi si prende la differenza. Questo ovviamente offre un contrasto molto maggiore per il blu su bianco rispetto al giallo su bianco.

0

Recentemente ho trovato la risposta su questa pagina, e ho usato il codice per creare uno script per Adobe Illustrator per calcolare il rapporto di contrasto.

Qui potete vedere il risultato: http://screencast.com/t/utT481Ut

Alcune delle notazioni abbreviate dello script sopra dove confusa per me e dove non funziona in Adobe estendere script. Quindi ho pensato che sarebbe stato bello condividere il mio miglioramento/interpretazione del codice condiviso dal kirilloid.

function luminance(r, g, b) { 
    var colorArray = [r, g, b]; 
    var colorFactor; 
    var i; 
    for (i = 0; i < colorArray.length; i++) { 
     colorFactor = colorArray[i]/255; 
     if (colorFactor <= 0.03928) { 
      colorFactor = colorFactor/12.92; 
     } else { 
      colorFactor = Math.pow(((colorFactor + 0.055)/1.055), 2.4); 
     } 
     colorArray[i] = colorFactor; 
    } 
    return (colorArray[0] * 0.2126 + colorArray[1] * 0.7152 + colorArray[2] * 0.0722) + 0.05; 
} 

E, naturalmente, è necessario chiamare questa funzione

all'interno di un ciclo for ricevo tutti i colori del mio oggetto illustratore

//just a snippet here to demonstrate the notation 
var selection = app.activeDocument.selection; 
for (i = 0; i < selection.length; i++) { 
    red[i] = selection[i].fillColor.red; 
    //I left out the rest,because it would become to long 
} 

//this can then be used to calculate the contrast ratio. 
var foreGround = luminance(red[0], green[0], blue[0]); 
var background = luminance(red[1], green[1], blue[1]); 
luminanceValue = foreGround/background; 
luminanceValue = round(luminanceValue, 2); 

//for rounding the numbers I use this function: 
function round(number, decimals) { 
    return +(Math.round(number + "e+" + decimals) + "e-" + decimals); 
} 

Maggiori informazioni su rapporto di contrasto: http://webaim.org/resources/contrastchecker/

0
module.exports = function colorcontrast (hex) { 
    var color = {}; 

    color.contrast = function(rgb) { 
     // check if we are receiving an element or element background-color 
     if (rgb instanceof jQuery) { 
      // get element background-color 
      rgb = rgb.css('background-color'); 
     } else if (typeof rgb !== 'string') { 
      return; 
     } 

     // Strip everything except the integers eg. "rgb(" and ")" and " " 
     rgb = rgb.split(/\(([^)]+)\)/)[1].replace(/ /g, ''); 

     // map RGB values to variables 
     var r = parseInt(rgb.split(',')[0], 10), 
      g = parseInt(rgb.split(',')[1], 10), 
      b = parseInt(rgb.split(',')[2], 10), 
      a; 

     // if RGBA, map alpha to variable (not currently in use) 
     if (rgb.split(',')[3] !== null) { 
      a = parseInt(rgb.split(',')[3], 10); 
     } 

     // calculate contrast of color (standard grayscale algorithmic formula) 
     var contrast = (Math.round(r * 299) + Math.round(g * 587) + Math.round(b * 114))/1000; 

     return (contrast >= 128) ? 'black' : 'white'; 
    }; 

    // Return public interface 
    return color; 

}; 
+0

Questo sembra buono, ma perché il metodo' colorcontrast' accetta l'argomento 'hex', ma quell'argomento non viene usato? – ctlockey

0

In base alla risposta del kirilloid:

Servizio angolare che calcola il contrasto e luminescenza passando il valore esadecimale:

.service('ColorContrast', [function() { 
var self = this; 

/** 
* Return iluminance value (base for getting the contrast) 
*/ 
self.calculateIlluminance = function(hexColor) { 
    return calculateIluminance(hexColor); 
}; 

/** 
* Calculate contrast value to white 
*/ 
self.contrastToWhite = function(hexColor){ 
    var whiteIlluminance = 1; 
    var illuminance = calculateIlluminance(hexColor); 
    return whiteIlluminance/illuminance; 
}; 

/** 
* Bool if there is enough contrast to white 
*/ 
self.isContrastOkToWhite = function(hexColor){ 
    return self.contrastToWhite(hexColor) > 4.5; 
}; 

/** 
* Convert HEX color to RGB 
*/ 
var hex2Rgb = function(hex) { 
    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 
    return result ? { 
     r: parseInt(result[1], 16), 
     g: parseInt(result[2], 16), 
     b: parseInt(result[3], 16) 
    } : null; 
}; 

/** 
* Calculate iluminance 
*/ 
var calculateIlluminance = function(hexColor) { 
    var rgbColor = hex2Rgb(hexColor); 
    var r = rgbColor.r, g = rgbColor.g, b = rgbColor.b; 
    var a = [r, g, b].map(function(v) { 
     v /= 255; 
     return (v <= 0.03928) ? 
      v/12.92 : 
      Math.pow(((v + 0.055)/1.055), 2.4); 
    }); 
    return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722; 
}; 

}]); 
Problemi correlati