diff --git a/src/color/p5.Color.js b/src/color/p5.Color.js index 888c9606d6..de91ea4906 100644 --- a/src/color/p5.Color.js +++ b/src/color/p5.Color.js @@ -8,6 +8,7 @@ import { RGB, RGBHDR, HSL, HSB, HWB, LAB, LCH, OKLAB, OKLCH } from './creating_reading'; + import { ColorSpace, to, @@ -25,7 +26,7 @@ import { OKLab, OKLCH as OKLCHSpace, - + contrastWCAG21, P3 } from 'colorjs.io/fn'; import HSBSpace from './color_spaces/hsb.js'; @@ -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 @@ -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 + * contrast checker tool. + * The contrast function in p5.js uses the WCAG 2.1 method the + * color.js contrast + * utility. + * + + * + * @param {Color} other + * @returns {{ ratio: Number }} + * @example + *
+ *
+ * // 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));
+ * }
+ *
+ *