Changer la couleur du texte en fonction de la luminosité de la zone d'arrière-plan couverte?

J'ai déjà pensé à ce sujet pendant un certain temps, alors maintenant je veux connaître vos opinions, vos solutions possibles, etc.

Je recherche un plugin ou une technique qui modifie la couleur d'un texte ou change entre des images / icônes prédéfinies en fonction de la luminosité moyenne des pixels couverts de l'image de fond ou de la couleur du parent.

Si la zone couverte de son fond est assez sombre, rendez le texte blanc ou changez les icônes.

En outre, il serait formidable que le script remarque si le parent n'a pas de couleur de fond ou d'image définie, puis continue de rechercher le plus proche (de l'élément parent à son élément parent …).

Qu'en pensez-vous, connaissez-vous cette idée? Y a-t-il déjà quelque chose de similaire? Exemples de script?

Cheers, J.

    Des ressources intéressantes pour cela:

    • W3C – Assurez-vous que les combinaisons de couleurs d'avant-plan et d'arrière-plan offrent un contraste suffisant
    • Calcul de la luminosité perçue d'une couleur

    Voici l'algorithme W3C (avec la démonstration JSFiddle aussi ):

    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; } 
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="bg">Text Example</div> 

    Cet article sur 24 façons de calcul du contraste de couleur pourrait vous intéresser. Ignorez le premier ensemble de fonctions car elles ont tort, mais la formule YIQ vous aidera à déterminer s'il faut ou non utiliser une couleur claire ou obscure.

    Une fois que vous obtenez la couleur d'arrière-plan de l'élément (ou de l'ancêtre), vous pouvez utiliser cette fonction à partir de l'article pour déterminer une couleur de premier plan appropriée:

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

    Question intéressante. Ma pensée immédiate était d'inverser la couleur de l'arrière-plan en tant que texte. Il s'agit simplement d'analyser l'arrière-plan et d'inverser sa valeur RVB.

    Quelque chose comme ceci: 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+')'); 

    J'ai trouvé le script BackgroundCheck très utile.

    Il détecte la luminosité excessive de l'arrière-plan (qu'il s'agisse d'une image d'arrière-plan ou d'une couleur) et applique une classe à l'élément de texte assigné ( background--light background--dark ou background--dark ), en fonction de la luminosité de l'arrière-plan.

    Il peut être appliqué aux éléments fixes et mobiles.

    ( Source )

    Voici ma tentative:

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

    Ensuite, pour l'utiliser:

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

    Cela va tout de suite, rendre le texte soit noir ou blanc, le cas échéant. Pour faire les icônes:

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

    Ensuite, chaque icône pourrait ressembler à 'save' + iconSuffix + '.jpg' .

    Notez que cela ne fonctionnera pas lorsque tout conteneur déborde son parent (par exemple, si la hauteur CSS est 0 et le débordement n'est pas caché). Pour obtenir ce travail serait beaucoup plus complexe.

    mix-blend-mode fait l'affaire:

     header { overflow: hidden; height: 100vh; background: url(https://www.w3schools.com/html/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); } 
     <header> <h2 contentEditable role='textbox' aria-multiline='true' >Edit me here</h2> </header>