Spiegare e codificare un correttore di contrasto

Apr 26 2023
Un cattivo contrasto si verifica quando la differenza di luminosità tra due colori su una pagina Web è troppo bassa, rendendo difficile per alcuni utenti, in particolare quelli con disabilità visive, distinguere tra i colori. Per aiutare i progettisti e gli sviluppatori a conformarsi agli standard di accessibilità, le Web Content Accessibility Guidelines (WCAG), pubblicate dal World Wide Web Consortium (W3C), specificano due livelli di conformità: AA e AAA.
Mi fanno male gli occhi guardando questa foto

Un cattivo contrasto si verifica quando la differenza di luminosità tra due colori su una pagina Web è troppo bassa, rendendo difficile per alcuni utenti, in particolare quelli con disabilità visive, distinguere tra i colori. Per aiutare i progettisti e gli sviluppatori a conformarsi agli standard di accessibilità, le Web Content Accessibility Guidelines (WCAG), pubblicate dal World Wide Web Consortium (W3C), specificano due livelli di conformità: AA e AAA. La conformità AA richiede un rapporto di contrasto di almeno 4,5:1 per il testo normale e 3:1 per il testo di grandi dimensioni. La conformità AAA richiede un rapporto di contrasto di almeno 7:1 per il testo normale e di 4,5:1 per il testo di grandi dimensioni.

Per calcolare il rapporto di contrasto, i correttori di contrasto utilizzano in genere la formula (L1 + 0,05) / (L2 + 0,05), dove L1 e L2 sono i valori di luminanza dei due colori confrontati. L'aggiunta di 0,05 a ciascun valore di luminanza è una piccola regolazione che aiuta a evitare errori di divisione per zero e garantisce che il rapporto di contrasto sia sempre compreso tra 1 e 21.

Mettendo in pratica la teoria, ho sviluppato questo semplice controllo del contrasto , che valuta il contrasto delle immagini inviate dagli utenti.

const fileInputElement = document.getElementById('fileInput');
const imageElement = document.getElementById('image');
const resultElement = document.getElementById('result');


fileInputElement.addEventListener('change', () => {

  const file = fileInputElement.files[0];
  const reader = new FileReader();
  reader.readAsDataURL(file);

  reader.onload = () => {
    imageElement.src = reader.result;
    imageElement.onload = () => {
      const contrastRatio = calculateContrastRatio(imageElement);
      displayResult(contrastRatio);
    }
  }
});


function calculateContrastRatio(image) {

  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d');
  canvas.width = image.width;
  canvas.height = image.height;


  context.drawImage(image, 0, 0);
  const imageData = context.getImageData(0, 0, image.width, image.height);
  const pixels = imageData.data;


  let lightestColor = 0;
  let darkestColor = 255;


  for (let i = 0; i < pixels.length; i += 4) {
    const red = pixels[i];
    const green = pixels[i + 1];
    const blue = pixels[i + 2];
    const alpha = pixels[i + 3] / 255;
    const luminance = 0.2126 * red + 0.7152 * green + 0.0722 * blue;


    lightestColor = Math.max(luminance, lightestColor);
    darkestColor = Math.min(luminance, darkestColor);
  }

  const contrastRatio = (lightestColor + 0.05) / (darkestColor + 0.05);
  return contrastRatio.toFixed(2);
}

function displayResult(contrastRatio) {
  let color;
  let message;

  if (contrastRatio >= 4.5) {
    color = 'green';
    message = `Contrast Ratio: ${contrastRatio}:1 (Passes WCAG 2.0 AA)`;
  } else if (contrastRatio >= 3) {
    color = 'orange';
    message = `Contrast Ratio: ${contrastRatio}:1 (Passes WCAG 2.0 AA for large text)`;
  } else {
    color = 'red';
    message = `Contrast Ratio: ${contrastRatio}:1 (Fails WCAG 2.0 AA)`;
  }


  resultElement.style.color = color;
  resultElement.textContent = message;
}

La calculateContrastRatiofunzione accetta un'immagine come argomento, crea una tela e un contesto e imposta la larghezza e l'altezza della tela in modo che corrispondano all'immagine. Quindi disegna l'immagine sulla tela e recupera un oggetto dati immagine dal contesto. Itera sui pixel dei dati dell'immagine, calcolando la luminanza di ciascun pixel e tenendo traccia dei colori più chiari e più scuri. Infine, calcola e restituisce il rapporto di contrasto tra i due colori.

La displayResultfunzione accetta un rapporto di contrasto come argomento e imposta il colore e il contenuto del testo di un elemento specificato in base al valore del rapporto. Se il rapporto è maggiore o uguale a 4,5, si considera che abbia superato le linee guida sull'accessibilità WCAG 2.0 AA e il messaggio è colorato in verde. Se il rapporto è maggiore o uguale a 3, viene considerato come testo grande e viene colorato in arancione. Se il rapporto è inferiore a 3, fallisce ed è colorato in rosso.

Naturalmente, questo codice può essere migliorato e ridimensionato per soddisfare altre esigenze relative all'accessibilità. Controlla il codice completo.