Cela fait déjà un moment que je réfléchis à ce qui suit: je veux maintenant connaître votre opinion, vos solutions possibles, etc.
Je recherche un plugin ou une technique permettant de changer la couleur d'un texte ou de basculer entre des images/icônes prédéfinies en fonction de la luminosité moyenne des pixels couverts de l'image ou de la couleur d'arrière-plan de son parent.
Si la partie couverte de l'arrière-plan est plutôt sombre, faites le texte en blanc ou changez les icônes.
De plus, il serait bon que le script remarque si le parent n'a pas de couleur d'arrière-plan ou d'image-définie, puis continue à rechercher le plus proche (de l'élément parent à son élément parent ..).
Que pensez-vous savoir de cette idée? Y a-t-il déjà quelque chose de similaire? exemples de script?
Cheers, J.
Ressources intéressantes pour cela:
Voici l'algorithme W3C (avec aussi une démo de 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;
}
<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 des couleurs pourrait vous intéresser. Ignorez le premier ensemble de fonctions car elles sont incorrectes, mais la formule YIQ vous aidera à déterminer si vous souhaitez utiliser une couleur de premier plan claire ou foncée.
Une fois que vous avez obtenu 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){
hexcolor = hexcolor.replace("#", "");
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 interessante. Ma pensée immédiate était d’inverser la couleur de l’arrière-plan en tant que texte. Cela implique 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+')');
mix-blend-mode
fait le tour:
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>
Ajout (mars 2018): Après, un tutoriel de Nice expliquant tous les différents types de modes/implémentations: https://css-tricks.com/css-techniques-and-effects-for-knockout-text/ =
J'ai trouvé le script BackgroundCheck très utile.
Il détecte la luminosité globale de l’arrière-plan (qu’il s’agisse d’une image de fond ou d’une couleur) et applique une classe à l’élément de texte attribué (background--light
ou background--dark
), en fonction de la luminosité de l'arrière-plan.
Il peut être appliqué aux éléments immobiles et en mouvement.
( Source )
Si vous utilisez ES6, convertissez hex en RVB puis pouvez utiliser ceci:
const hexToRgb = hex => {
// turn hex val to RGB
const 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
}
// 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))
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));
Puis l'utiliser:
var t = $('#my-el');
t.contrastingText();
Cela va tout de suite rendre le texte noir ou blanc selon le cas. 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 si un conteneur déborde de son parent (par exemple, si la hauteur CSS est 0 et que le débordement n'est pas masqué). Pour que cela fonctionne, ce serait beaucoup plus complexe.