Table des matières
plan
Étape 1: Lisez la couleur de l'image de la toile
Étape 2: Trouvez le pixel avec le moins de contraste
Étape 3: Préparez la formule de mélange de couleurs pour tester le niveau d'opacité de superposition
Étape 4: Trouvez l'opacité de superposition qui atteint la cible de contraste
Améliorations et limitations
J'ai appris quelque chose en cours de route
Maison interface Web tutoriel CSS Nouer le contraste parfait entre le texte léger et une image d'arrière-plan

Nouer le contraste parfait entre le texte léger et une image d'arrière-plan

Apr 03, 2025 am 09:44 AM

Nouer le contraste parfait entre le texte léger et une image d'arrière-plan

Avez-vous déjà rencontré du texte léger sur un site Web superposé à une image d'arrière-plan légère? Si vous l'avez rencontré, vous saurez à quel point il est difficile de lire. Une façon courante d'éviter cela est d'utiliser une superposition transparente. Mais cela soulève une question importante: quelle est la hauteur de la transparence de la superposition? Nous ne traitons pas toujours avec la même taille, épaisseur et couleur, et bien sûr, différentes images produiront également un contraste différent.

Essayez d'éliminer le problème du mauvais contraste de texte sur l'image de fond, tout comme jouer au jeu Goblin. Plutôt que de deviner, utilisez HTML<canvas></canvas> Et quelques méthodes mathématiques pour résoudre ce problème.

Comme ça:

Nous pouvons dire "le problème est résolu!" puis terminer cet article. Mais quel est le plaisir de cela? Ce que je veux vous montrer, c'est comment cet outil fonctionne afin que vous puissiez maîtriser une nouvelle façon de faire face à ce problème commun.

plan

Tout d'abord, clarifions nos objectifs. Nous avons dit que nous voulons afficher du texte lisible sur l'image d'arrière-plan, mais que signifie exactement "lisible"? Pour nos besoins, nous utiliserons la définition de la lisibilité au niveau de l'AA-AA, qui indique qu'il est nécessaire de contraster suffisamment entre le texte et les couleurs d'arrière-plan afin qu'une couleur soit 4,5 fois plus brillant que l'autre.

Choisissons une couleur de texte, une image d'arrière-plan et une couleur de superposition comme point de départ. Compte tenu de ces entrées, nous voulons trouver un niveau d'opacité de superposition qui rend le texte lisible sans cacher tellement l'image que l'image est difficile à voir. Pour compliquer un peu les choses, nous utiliserons une image qui a à la fois des couleurs sombres et claires, et nous assurer que la superposition en prend en compte.

Notre résultat final sera une valeur que nous pouvons appliquer à la propriété CSS Opacity de la superposition, ce qui rend le texte 4,5 fois plus brillant que l'arrière-plan.

Pour trouver la meilleure opacité de superposition, nous effectuerons quatre étapes:

  1. Nous mettons l'image dans HTML<canvas></canvas> Cela nous permettra de lire la couleur de chaque pixel de l'image.
  2. Nous trouverons les pixels dans l'image qui ont le moins de contraste avec le texte.
  3. Ensuite, nous préparerons une formule de mélange de couleurs que nous pouvons utiliser pour tester l'effet de différents niveaux d'opacité sur la couleur de ce pixel.
  4. Enfin, nous allons ajuster l'opacité de la superposition jusqu'à ce que le contraste du texte atteigne l'objectif de lisibilité. Ce ne sera pas deviner aléatoire - nous utiliserons des techniques de recherche binaires pour accélérer ce processus.

Commençons!

Étape 1: Lisez la couleur de l'image de la toile

La toile nous permet de "lire" les couleurs contenues dans l'image. Pour ce faire, nous devons "dessiner" l'image pour<canvas></canvas> Sur l'élément, utilisez ensuite getImageData() du contexte Canvas (CTX) pour générer une liste de couleurs d'image.

 fonction getImagePixelColorsusingCanvas (image, canvas) {
  // Le contexte de la toile (généralement abrégé en CTX) est un objet contenant de nombreuses fonctions pour contrôler votre toile
  const ctx = canvas.getContext ('2d');

  // La largeur peut être n'importe quelle valeur, donc j'ai choisi 500 car elle est suffisamment grande pour capturer les détails, mais suffisamment petit pour rendre le calcul plus rapide.
  canevas.width = 500;

  // Assurez-vous que Canvas correspond à l'échelle de notre image canvas.height = (image.height / image.width) * canvas.width;

  // Obtenez les mesures de l'image et du canevas afin que nous puissions les utiliser dans l'étape suivante SourceImageCoORDINATS = [0, 0, Image.Width, Image.Height];
  const de destinationCanvasCoOrdines = [0, 0, canvas.width, canvas.height];

  // Canvas 'DrawImage () fonctionne en cartographiant les mesures de notre image à la toile que nous voulons la dessiner sur ctx.DrawImage (
    image,
    ... SourceMagecoordonate,
    ... DestinationCanvasCoOrdine
  ));

  // N'oubliez pas que GetImagedata ne fonctionne qu'avec des images avec la même source ou l'origine transversale activée.
  // https://developer.mozilla.org/en-us/docs/web/html/cors_enabled_image
  const imagePixelColors = ctx.getImagedata (... DestinationCanvasCoOrdine);
  return ImagePixElColors;
}
Copier après la connexion

getImageData() nous fournit une liste de nombres représentant la couleur de chaque pixel. Chaque pixel est représenté par quatre nombres: rouge, vert, bleu et opacité (également connu sous le nom de "alpha". Sachant cela, nous pouvons parcourir la liste des pixels et trouver toutes les informations dont nous avons besoin. Ce sera très utile à l'étape suivante.

Étape 2: Trouvez le pixel avec le moins de contraste

Avant cela, nous devons savoir comment calculer le contraste. Nous rédigerons une fonction appelée getContrast() qui prend deux couleurs et sortira un nombre indiquant le niveau de contraste entre les deux couleurs. Plus les chiffres sont élevés, mieux c'est le contraste et mieux la lisibilité.

Lorsque j'ai commencé à rechercher les couleurs de ce projet, je m'attendais à trouver une formule simple. Il s'est avéré qu'il y avait plusieurs étapes.

Pour calculer le contraste entre deux couleurs, nous devons connaître leur niveau de luminosité, qui est essentiellement la luminosité (Stacie Arellano a un aperçu approfondi de la luminosité, ce qui vaut le coup).

Grâce à W3C, nous connaissons la formule pour calculer le contraste à l'aide de la luminosité:

 CONSTAST CONSTAGE = (LighterColorLuminance 0,05) / (Darkercolorluminance 0,05);
Copier après la connexion

Obtenir la luminosité de la couleur signifie que nous devons convertir la couleur de la valeur RVB 8 bits ordinaire utilisée sur le réseau (où chaque couleur est 0-255) en ce qui est appelé RVB linéaire. Nous devons le faire car la luminosité n'augmente pas uniformément avec le changement de couleur. Nous devons convertir la couleur en un format où la luminosité change uniformément avec la couleur. Cela nous permet de calculer correctement la luminosité. De même, W3C fournit une aide ici:

 const Luminance = (0,2126 * getLineArrgb (r) 0,7152 * getlineArrgb (g) 0,0722 * getlineArrgb (b));
Copier après la connexion

Mais attendez, il y en a plus! Afin de convertir le RVB 8 bits (0 à 255) en RVB linéaire, nous devons passer par ce qui est appelé RVB standard (également connu sous le nom de SRGB), qui a un rapport de 0 à 1.

Par conséquent, le processus est le suivant:

 <code>8位RGB → 标准RGB → 线性RGB → 亮度</code>
Copier après la connexion

Une fois que nous avons la luminosité des deux couleurs que nous voulons comparer, nous pouvons remplacer les valeurs de luminosité dans la formule pour obtenir le contraste entre leurs couleurs respectives.

 // getContrast est la seule fonction dont nous avons besoin pour interagir directement.
// Les autres fonctions sont des étapes auxiliaires intermédiaires.
fonction getContrast (Color1, Color2) {
  const Color1_Luminance = GetLuminance (Color1);
  const Color2_Luminance = GetLuminance (Color2);
  const LighterColorLuminance = Math.max (Color1_Luminance, Color2_Luminance);
  const darkercolorluminance = math.min (color1_luminance, color2_luminance);
  CONSTAST CONSTAGE = (LighterColorLuminance 0,05) / (Darkercolorluminance 0,05);
  Retour contraste;
}

fonction getluminance ({r, g, b}) {
  retour (0,2126 * getlineArrgb (r) 0,7152 * getlineArrgb (g) 0,0722 * getLineArrgb (b));
}
function getlineArrgb (primorColor_8bit) {
  // Convertir d'abord de RVB 8 bits (0-255) en RVB standard (0-1)
  const primairecolor_srgb = convert_8bit_rgb_to_standard_rgb (primairecolor_8bit);

  // ensuite converti de SRGB en RVB linéaire afin que nous puissions l'utiliser pour calculer la luminosité const primairecolor_rgb_linear = convert_standard_rgb_to_linear_rgb (primorcolor_srgb);
  return primorColor_rgb_linear;
}
fonction convert_8bit_rgb_to_standard_rgb (primairecolor_8bit) {
  return primorColor_8bit / 255;
}
fonction convert_standard_rgb_to_linear_rgb (primairecolor_srgb) {
  const primatcolor_linear = primairecolor_srgb <p> Maintenant que nous pouvons calculer le contraste, nous devons regarder l'image à l'étape précédente et itérer à travers chaque pixel pour comparer le contraste entre la couleur de ce pixel et la couleur du texte de premier plan. Lorsque nous traversons les pixels de l'image, nous suivrons le pire contraste (le plus bas) jusqu'à présent, et lorsque nous atteindrons la fin de la boucle, nous connaîtrons la couleur avec le pire contraste de l'image.</p><pre class="brush:php;toolbar:false"> function getworkStContrastColoriNimage (textColor, imagePixelColors) {
  Laissez le pireContrastColorinimage;
  Laissez le pire-contraste = infinité; // Cela garantit que nous ne commençons pas par une valeur trop faible pour (que i = 0; i <imagepixelcolors.data.length i="4)" const r="imagePixelColors.data" g="imagePixelColors.data" b="imagePixelColors.data" imagepixelcolor="{r," contrast="getContrast" if pirecontrast="contraste;" pirecontrastcolorinimage="ImagePixelColor;" retourner><p></p>
<h3 id="Étape-Préparez-la-formule-de-mélange-de-couleurs-pour-tester-le-niveau-d-opacité-de-superposition"> Étape 3: Préparez la formule de mélange de couleurs pour tester le niveau d'opacité de superposition</h3>
<p></p>
<p> Maintenant que nous connaissons la couleur avec le pire contraste de notre image, l'étape suivante consiste à déterminer la hauteur de la transparence de la superposition et de voir comment cela changera le contraste avec le texte.</p>
<p></p>
<p> Lorsque j'ai implémenté cela pour la première fois, j'ai utilisé une toile séparée pour mélanger les couleurs et lire les résultats. Cependant, grâce à l'article d'Ana Tudor sur la transparence, je sais maintenant qu'il existe une formule pratique pour calculer la couleur résultante après avoir mélangé la couleur de base avec la superposition transparente.</p>
<p></p>
<p> Pour chaque canal de couleur (rouge, vert et bleu), nous appliquerons cette formule pour obtenir les couleurs mélangées:</p>
<p> Couleur mélangée = couleur de base (couleur de chevauchement - couleur de base) * Opacité qui se chevauche</p>
<p></p>
<p> Donc, dans le code, cela ressemblera à ceci:</p>
<pre class="brush:php;toolbar:false"> Fonction MixColors (BaseColor, superlaycolor, superlayopacity) {
  const mixtescolor = {
    R: BaseColor.R (superlaycolor.r - BaseColor.R) * Overlayopacity,
    G: BaseColor.g (superlaycolor.g - basecolor.g) * superlayopacity,
    B: BaseColor.B (overlayColor.B - BaseColor.B) * Overlayopacity,
  }
  retour mixtecolor;
}
Copier après la connexion

Maintenant que nous pouvons mélanger les couleurs, nous pouvons tester le contraste lors de l'application de valeurs d'opacité de superposition.

 function getTextContrastWithImagePlusOverlay ({textColor, overlayColor, imagePixelColor, superlayopacity}) {
  const ColoroFimagePixelPlusOverlay = mixColors (imagePixelColor, overlayColor, superlayopacity);
  const Contrast = GetContrast (textColor, ColoroFimagePixelPlusOverlay);
  Retour contraste;
}
Copier après la connexion

Avec cela, nous avons tous les outils dont nous avons besoin pour trouver la meilleure opacité de superposition!

Étape 4: Trouvez l'opacité de superposition qui atteint la cible de contraste

Nous pouvons tester l'opacité de la superposition et voir comment cela affectera le contraste entre le texte et l'image. Nous essaierons de nombreux niveaux d'opacité différents jusqu'à ce que nous trouvions une valeur qui atteint le contraste cible, où le texte est 4,5 fois plus brillant que l'arrière-plan. Cela peut sembler fou, mais ne vous inquiétez pas; Nous ne devinerons pas au hasard. Nous utiliserons la recherche binaire, un processus qui nous permet de réduire rapidement les ensembles de réponses possibles jusqu'à ce que nous obtenions des résultats précis.

Voici comment fonctionne la recherche binaire:

 <code>- 在中间猜测。 - 如果猜测过高,我们将消除答案的上半部分。太低了吗?我们将改为消除下半部分。 - 在新的范围中间猜测。 - 重复此过程,直到我们得到一个值。我碰巧有一个工具可以展示它是如何工作的:在这种情况下,我们试图猜测一个介于0和1之间的不透明度值。因此,我们将从中间猜测,测试结果对比度是太高还是太低,消除一半的选项,然后再次猜测。如果我们将二分查找限制为八次猜测,我们将立即得到一个精确的答案。在我们开始搜索之前,我们需要一种方法来检查是否根本需要叠加层。我们根本不需要优化我们不需要的叠加层! ```javascript function isOverlayNecessary(textColor, worstContrastColorInImage, desiredContrast) { const contrastWithoutOverlay = getContrast(textColor, worstContrastColorInImage); return contrastWithoutOverlay </code>
Copier après la connexion

Maintenant, nous pouvons utiliser la recherche binaire pour trouver la meilleure opacité de superposition:

 fonction findOptimalOverLaYOPacity (textColor, overlayColor, pire
  // Si le contraste est assez bon, nous n'avons pas besoin de superposer,
  // Nous pouvons donc sauter le reste.
  const isOverlayneceSsary = isOverlaynecessary (textColor, pireContrastColoriniMage, désiréContrasse);
  if (! isOverlaynessary) {
    retour 0;
  }

  const OpacityGuessRange = {
    basse: 0,
    Point médian: 0,5,
    Upperbound: 1,
  };
  Soit NumberOfGuesses = 0;
  const maxguess = 8;

  // S'il n'y a pas de solution, l'opacité sera proche de 1,
  // Nous pouvons donc l'utiliser comme limite supérieure pour vérifier la situation sans solutions.
  Const OpacityLimit = 0,99;

  // Cette boucle rétrécit à plusieurs reprises notre supposition jusqu'à ce que nous obtenions le résultat pendant (nombre de prudences <maxguess nombre de gar const currentguess="opacityGuessRange.MIDPoint;" contrast="getTextContrastWithImagePlusOverlay" overlaycolor imagepixelcolor: pirecontrastcolorinimage overlayopacity: currentgeess isguesstoolow="contraste" isguesstoohigh="contraste"> désiredContrast;

    if (isGuesstoolow) {
      OpacityGuessRange.LowerBound = CurrentGuess;
    }
    else if (isGuesstooHigh) {
      opacityGuessRange.upperbound = currentGuess;
    }

    const newMidpoint = ((opacityGuessRange.upperbound - opacityGuessRange.LowerBound) / 2) OpacityGuessRange.LowerBound;
    opacityGuessRange.midpoint = newMidPoint;
  }

  const OptimalOpacity = opacityGuessRange.midpoint;
  const Hasnosolution = OptimalOpacity> OpacityLimit;

  if (Hasnosolution) {
    console.log («pas de solution»); // gérer les situations insolubles au besoin RETOUR OPCACITYLIMIT;
  }
  Retour OptimalOpacity;
}</maxguess>
Copier après la connexion

Une fois l'expérience terminée, nous savons maintenant exactement à quel point la superposition doit être transparente pour rendre le texte lisible sans cacher trop d'images d'arrière-plan.

Nous l'avons fait!

Améliorations et limitations

La méthode que nous introduisons n'est efficace que si la couleur du texte et la couleur de superposition elles-mêmes ont un contraste suffisant. Par exemple, si vous choisissez la même couleur de texte que la superposition, il n'y aura pas de solution optimale à moins que l'image ne nécessite de superposition du tout.

De plus, même si le contraste est mathématiquement acceptable, cela ne garantit pas toujours qu'il a fière allure. Cela est particulièrement vrai pour le texte sombre avec des superpositions légères et des images d'arrière-plan occupées. Des parties de l'image peuvent distraire du texte et peuvent être difficiles à lire même si le contraste est numériquement bon. C'est pourquoi le conseil populaire est d'utiliser du texte clair sur des arrière-plans sombres.

Nous n'avons pas non plus considéré la position des pixels ou le nombre de pixels par couleur. Un inconvénient de cela est que les pixels dans les coins peuvent avoir un impact excessif sur les résultats. Mais l'avantage est que nous n'avons pas à nous soucier de la façon dont les couleurs de l'image sont distribuées ou où se trouve le texte, car tant que nous traitons des endroits avec le moins de contraste, nous pouvons être en sécurité ailleurs.

J'ai appris quelque chose en cours de route

Après cette expérience, j'ai gagné quelque chose et je veux le partager avec vous:

 <code>- **明确目标非常有帮助!**我们从一个模糊的目标开始,即想要在图像上显示可读的文本,最终得到了一个我们可以努力达到的特定对比度级别。 - **明确术语非常重要。**例如,标准RGB并非我所期望的。我了解到,我认为的“常规”RGB(0到255)正式称为8位RGB。此外,我认为我研究的方程式中的“L”表示“亮度”,但它实际上表示“亮度”,这不能与“光度”混淆。澄清术语有助于我们编写代码以及讨论最终结果。 - **复杂并不意味着无法解决。**听起来很困难的问题可以分解成更小、更容易管理的部分。 - **当你走过这条路时,你会发现捷径。**对于白色文本在黑色透明叠加层上的常见情况,您永远不需要超过0.54的不透明度即可达到WCAG AA级可读性。 ### 总结…您现在有了一种方法可以在背景图像上使文本可读,而不会牺牲过多的图像。如果您已经读到这里,我希望我已经能够让您大致了解其工作原理。我最初开始这个项目是因为我看到(并制作了)太多网站横幅,其中文本在背景图像上难以阅读,或者背景图像被叠加层过度遮挡。我想做些什么,我想给其他人提供一种同样的方法。我写这篇文章是为了希望你们能够更好地理解网络上的可读性。我希望你们也学习了一些很酷的canvas技巧。如果您在可读性或canvas方面做了一些有趣的事情,我很乐意在评论中听到您的想法!</code>
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Vue 3 Vue 3 Apr 02, 2025 pm 06:32 PM

Il est sorti! Félicitations à l'équipe Vue pour l'avoir fait, je sais que ce fut un effort massif et une longue période à venir. Tous les nouveaux documents aussi.

Pouvez-vous obtenir des valeurs de propriété CSS valides du navigateur? Pouvez-vous obtenir des valeurs de propriété CSS valides du navigateur? Apr 02, 2025 pm 06:17 PM

J'ai eu quelqu'un qui écrivait avec cette question très légitime. Lea vient de bloguer sur la façon dont vous pouvez obtenir les propriétés CSS valides elles-mêmes du navigateur. C'est comme ça.

Un peu sur CI / CD Un peu sur CI / CD Apr 02, 2025 pm 06:21 PM

Je dirais que "Site Web" correspond mieux que "Application mobile" mais j'aime ce cadrage de Max Lynch:

Utilisation de Markdown et de la localisation dans l'éditeur de blocs WordPress Utilisation de Markdown et de la localisation dans l'éditeur de blocs WordPress Apr 02, 2025 am 04:27 AM

Si nous devons afficher la documentation à l'utilisateur directement dans l'éditeur WordPress, quelle est la meilleure façon de le faire?

Cartes empilées avec un positionnement collant et une pincée de sass Cartes empilées avec un positionnement collant et une pincée de sass Apr 03, 2025 am 10:30 AM

L'autre jour, j'ai repéré ce morceau particulièrement charmant sur le site Web de Corey Ginnivan où une collection de cartes se cassent les uns sur les autres pendant que vous faites défiler.

Comparaison des navigateurs pour une conception réactive Comparaison des navigateurs pour une conception réactive Apr 02, 2025 pm 06:25 PM

Il existe un certain nombre de ces applications de bureau où l'objectif montre votre site à différentes dimensions en même temps. Vous pouvez donc, par exemple, écrire

Comment utiliser la grille CSS pour les en-têtes et pieds de page collants Comment utiliser la grille CSS pour les en-têtes et pieds de page collants Apr 02, 2025 pm 06:29 PM

CSS Grid est une collection de propriétés conçues pour faciliter la mise en page qu'elle ne l'a jamais été. Comme tout, il y a un peu une courbe d'apprentissage, mais Grid est

Fontes variables de polices Google Fontes variables de polices Google Apr 09, 2025 am 10:42 AM

Je vois que Google Fonts a déployé un nouveau design (tweet). Comparé à la dernière grande refonte, cela semble beaucoup plus itératif. Je peux à peine faire la différence

See all articles