Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 98 additions & 1 deletion src/color/p5.Color.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import { RGB, RGBHDR, HSL, HSB, HWB, LAB, LCH, OKLAB, OKLCH } from './creating_reading';


import {
ColorSpace,
to,
Expand All @@ -25,7 +26,7 @@ import {

OKLab,
OKLCH as OKLCHSpace,

contrastWCAG21,
P3
} from 'colorjs.io/fn';
import HSBSpace from './color_spaces/hsb.js';
Expand All @@ -41,6 +42,9 @@ const map = (n, start1, stop1, start2, stop2, clamp) => {

const serializationMap = {};




class Color {
// Reference to underlying color object depending on implementation
// Not meant to be used publicly unless the implementation is known for sure
Expand Down Expand Up @@ -326,6 +330,99 @@ class Color {
return colorString;
}

/**
* Checks the contrast between two colors, to make sure that they
* are different enough to be readable. The result of this function is
* a color contrast ratio that can be compared to `COLOR_CONTRAST_MINIMUM_GRAPHICS`,
* or to `COLOR_CONTRAST_MINIMUM_TEXT`. The higher the ratio, the more
* different colors are, and the more legible to a user.
*
* Graphics, interface elements, and large text should have a color
* contrast ratio of at least 4.5 (`COLOR_CONTRAST_MINIMUM_GRAPHICS`)
*
* Smaller text - less than at least 14 point or 19 pixels -
* should have a color contrast ratio of at least 7
* (`COLOR_CONTRAST_MINIMUM_TEXT`)
*
* The constants are based on WCAG AAA recommendations, which you can also explore in this
* <a href="https://webaim.org/resources/contrastchecker/">contrast checker tool</a>.
* The contrast function in p5.js uses the WCAG 2.1 method the
* <a href="https://colorjs.io/docs/contrast.html">color.js contrast</a>
* utility.
*

*
* @param {Color} other
* @returns {{ ratio: Number }}
* @example
* <div>
* <code>
*
* // The contrast checker can be used both during development
* // with `print()`, or to help select readable colors on the fly.
* // This example shows both uses.
*
* let bgColor;
* let fg1Color;
* let fg2Color;
*
* function setup() {
* createCanvas(100, 100);
* bgColor = color(0);
* fg1Color = color(120);
* fg2Color = color(255);
*
* describe('A small square canvas with acentered text outlined by a thick stroke. The text reads 'click again!'. On every mouse click, the background, square outline, and text colors randomize, with high enough contrast for readability.');
* }
*
* function draw() {
* background(bgColor);
* stroke(fg1Color);
* noFill();
* strokeWeight(5);
* rect(10, 10, 80, 80);
*
* noStroke();
* fill(fg2Color);
* textAlign(CENTER, CENTER);
* textSize(20);
* text("click\nagain!", 50, 50);
* }
*
* function mouseClicked(){
* let newBgColor;
* let newFg1Color;
* let newFg2Color;
*
* // The loop may go for a long time, but it will not go on forever
* // It will stop the first time that the random colors contrast enough
* for (let i = 0; i < 10000; i += 1){
* newBgColor = color(random(255), random(255), random(255));
* newFg1Color = color(random(255), random(255), random(255));
* newFg2Color = color(random(255), random(255), random(255));
* if (
* newBgColor.contrast(newFg2Color) >= COLOR_CONTRAST_MINIMUM_TEXT &&
* newBgColor.contrast(newFg1Color) >= COLOR_CONTRAST_MINIMUM_GRAPHICS &&
* newBgColor.contrast(newFg1Color) < COLOR_CONTRAST_MINIMUM_TEXT ){
*
* bgColor = newBgColor;
* fg1Color = newFg1Color;
* fg2Color = newFg2Color;
*
* break;
* }
* }
*
* print("Contrast (rect)", bgColor.contrast(fg1Color));
* print("Contrast (text)", bgColor.contrast(fg2Color));
* }
* </code>
* </div>
*/
contrast(other_color) {
return contrastWCAG21(this._color, other_color._color);
};

/**
* Sets the red component of a color.
*
Expand Down
19 changes: 19 additions & 0 deletions src/core/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -1371,3 +1371,22 @@ export const EXCLUDE = Symbol('exclude');
* @private
*/
export const JOIN = Symbol('join');

/**
* Can be used with `Color.contrast` to check if graphics, UI elements, and large text
* have enough contrast.
* @typedef {'color-contrast-minimum-graphics'} COLOR_CONTRAST_MINIMUM_GRAPHICS
* @property {COLOR_CONTRAST_MINIMUM_GRAPHICS} COLOR_CONTRAST_MINIMUM_GRAPHICS
* @final
*/
export const COLOR_CONTRAST_MINIMUM_GRAPHICS = 4.5;


/**
* Can be used with `Color.contrast` to check if text smaller than 14pt (~19px)
* has enough contrast.
* @typedef {'color-contrast-minimum-text'} COLOR_CONTRAST_MINIMUM_TEXT
* @property {COLOR_CONTRAST_MINIMUM_TEXT} COLOR_CONTRAST_MINIMUMD_TEXT
* @final
*/
export const COLOR_CONTRAST_MINIMUM_TEXT = 7.0;
Loading