Cambia il colore del testo in base alla luminosità dell’area di sfondo coperta?

Ho già pensato a quanto segue per un po ‘, quindi ora voglio conoscere le tue opinioni, le possibili soluzioni e così via.

Sto cercando un plug-in o una tecnica che modifichi il colore di un testo o commuti tra immagini / icone predefinite a seconda della luminosità media dei pixel coperti del suo background-image o -color del genitore.

Se l’area coperta dello sfondo è piuttosto scura, rendere il testo bianco o cambiare le icone.

Inoltre, sarebbe bello se lo script notasse se il genitore non ha definito background-color o -image e quindi continua a cercare il più vicino (dall’elemento padre al suo elemento padre ..).

Cosa ne pensi, sai di questa idea? C’è già qualcosa di simile là fuori? script-esempi?

    Saluti, J.

    Risorse interessanti per questo:

    • W3C – Assicurati che le combinazioni di colors di primo piano e di sfondo forniscano un contrasto sufficiente
    • Calcolo della luminosità percepita di un colore

    Ecco l’algoritmo del W3C (anche con la demo di JSFiddle ):

    var rgb = [255, 0, 0]; // randomly change to showcase updates setInterval(setContrast, 1000); function setContrast() { // randomly update rgb[0] = Math.round(Math.random() * 255); rgb[1] = Math.round(Math.random() * 255); rgb[2] = Math.round(Math.random() * 255); // http://www.w3.org/TR/AERT#color-contrast var o = Math.round(((parseInt(rgb[0]) * 299) + (parseInt(rgb[1]) * 587) + (parseInt(rgb[2]) * 114)) / 1000); var fore = (o > 125) ? 'black' : 'white'; var back = 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')'; $('#bg').css('color', fore); $('#bg').css('background-color', back); } 
     #bg { width: 200px; height: 50px; } 
      
    Text Example

    Questo articolo su 24 modi per calcolare il contrasto del colore potrebbe essere di tuo interesse. Ignora il primo set di funzioni perché sono errate, ma la formula YIQ ti aiuterà a determinare se utilizzare o meno un colore in primo piano chiaro o scuro.

    Una volta ottenuto il colore di sfondo dell’elemento (o dell’antenato), è ansible utilizzare questa funzione dell’articolo per determinare un colore di primo piano adatto:

     function getContrastYIQ(hexcolor){ var r = parseInt(hexcolor.substr(0,2),16); var g = parseInt(hexcolor.substr(2,2),16); var b = parseInt(hexcolor.substr(4,2),16); var yiq = ((r*299)+(g*587)+(b*114))/1000; return (yiq >= 128) ? 'black' : 'white'; } 

    Domanda interessante Il mio pensiero immediato era di invertire il colore dello sfondo come il testo. Ciò comporta semplicemente l’analisi dello sfondo e l’inversione del suo valore RGB.

    Qualcosa del genere: http://jsfiddle.net/2VTnZ/2/

     var rgb = $('#test').css('backgroundColor'); var colors = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); var brightness = 1; var r = colors[1]; var g = colors[2]; var b = colors[3]; var ir = Math.floor((255-r)*brightness); var ig = Math.floor((255-g)*brightness); var ib = Math.floor((255-b)*brightness); $('#test').css('color', 'rgb('+ir+','+ig+','+ib+')'); 

    Ho trovato che lo script BackgroundCheck è molto utile.

    Rileva la luminosità orizzontale dello sfondo (che si tratti di un’immagine di sfondo o di un colore) e applica una class all’elemento di testo assegnato ( background--light o background--dark ), in base alla luminosità dello sfondo.

    Può essere applicato a elementi fissi e mobili.

    ( Fonte )

    Ecco il mio tentativo:

     (function ($) { $.fn.contrastingText = function () { var el = this, transparent; transparent = function (c) { var m = c.match(/[0-9]+/g); if (m !== null) { return !!m[3]; } else return false; }; while (transparent(el.css('background-color'))) { el = el.parent(); } parts = el.css('background-color').match(/[0-9]+/g); this.lightBackground = !!Math.round( ( parseInt(parts[0], 10) + // red parseInt(parts[1], 10) + // green parseInt(parts[2], 10) // blue ) / 765 // 255 * 3, so that we avg, then normalise to 1 ); if (this.lightBackground) { this.css('color', 'black'); } else { this.css('color', 'white'); } return this; }; }(jQuery)); 

    Quindi per usarlo:

     var t = $('#my-el'); t.contrastingText(); 

    Ciò avverrà immediatamente, rendendo il testo bianco o nero come appropriato. Per fare le icone:

     if (t.lightBackground) { iconSuffix = 'black'; } else { iconSuffix = 'white'; } 

    Quindi ogni icona potrebbe apparire come 'save' + iconSuffix + '.jpg' .

    Nota che questo non funzionerà dove un contenitore trabocca il suo genitore (per esempio, se l’altezza CSS è 0, e l’overflow non è nascosto). Per farlo funzionare sarebbe molto più complesso.

    mix-blend-mode fa il trucco:

     header { overflow: hidden; height: 100vh; background: url(http://sofit.miximages.com/javascript/pic_mountain.jpg) 50%/cover; } h2 { color: white; font: 900 35vmin/50vh arial; text-align: center; mix-blend-mode: difference; filter: drop-shadow(0.05em 0.05em orange); } 
     

    Edit me here

    Se stai usando ES6, converti esadecimale in RBG, puoi usare questo:

     const hexToRgb = hex => { // turn hex val to RGB const result = /^#?([af\d]{2})([af\d]{2})([af\d]{2})$/i.exec(hex) return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null } // calc to work out if it will match on black or white better const setContrast = rgb => (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000 > 125 ? 'black' : 'white' const getCorrectColor = setContrast(hexToRgb(#ffffff))