Skip to content

Commit a79b653

Browse files
committed
contrast function first PR
1 parent b606575 commit a79b653

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

src/color/p5.Color.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828

2929
P3
3030
} from 'colorjs.io/fn';
31+
3132
import HSBSpace from './color_spaces/hsb.js';
3233

3334
const map = (n, start1, stop1, start2, stop2, clamp) => {
@@ -41,6 +42,17 @@ const map = (n, start1, stop1, start2, stop2, clamp) => {
4142

4243
const serializationMap = {};
4344

45+
const SRGB_THRESHOLD = 0.03928;
46+
const SRGB_DIVISOR = 12.92;
47+
const GAMMA_OFFSET = 0.055;
48+
const GAMMA_DIVISOR = 1.055;
49+
const GAMMA_EXPONENT = 2.4;
50+
const LUMINANCE_RED = 0.2126;
51+
const LUMINANCE_GREEN = 0.7152;
52+
const LUMINANCE_BLUE = 0.0722;
53+
const EPSILON = 0.05;
54+
const THRESHOLD = 4.5;
55+
4456
class Color {
4557
// Reference to underlying color object depending on implementation
4658
// Not meant to be used publicly unless the implementation is known for sure
@@ -291,6 +303,58 @@ class Color {
291303
return colorString;
292304
}
293305

306+
/**
307+
* Checks if two colors contrast ratio is WCAG 2.1 compliant and returns the ratio
308+
*
309+
* @param {Color} other
310+
* @returns {{ ratio: Number, passes: boolean }}
311+
* @example
312+
* <div>
313+
* <code>
314+
*
315+
* function setup() {
316+
* // Define colors
317+
* let color1 = color(255, 255, 255);
318+
* let color2 = color(0);
319+
*
320+
* // Test for contrast
321+
* let result = color1.contrast(color2)
322+
*
323+
* console.log(result)
324+
*
325+
* }
326+
* </code>
327+
* </div>
328+
*/
329+
330+
contrast(new_other) {
331+
//Constants for contrast ratio cutoffs
332+
const CONTRAST_AA_NORMAL = 4.5;
333+
const CONTRAST_AA_LARGE = 3.0;
334+
const CONTRAST_AAA_NORMAL = 7.0;
335+
const CONTRAST_AAA_LARGE = 4.5;
336+
337+
//helper function for luminance aka brightness
338+
let luminance = (c) => {
339+
//putting RGB values into array and convert colors to value between 0-1
340+
let rgb = [red(c), green(c), blue(c)].map(v => {
341+
v /= 255;
342+
return v <= SRGB_THRESHOLD
343+
? v / SRGB_DIVISOR
344+
: Math.pow((v + GAMMA_OFFSET) / GAMMA_DIVISOR, GAMMA_EXPONENT);
345+
});
346+
return LUMINANCE_RED * rgb[0] + LUMINANCE_GREEN * rgb[1] + LUMINANCE_BLUE * rgb[2];
347+
};
348+
349+
let l1 = luminance(this);
350+
let l2 = luminance(new_other);
351+
//Epsilon to avoid dividing by zero
352+
let ratio = (Math.max(l1, l2) + EPSILON) / (Math.min(l1, l2) + EPSILON);
353+
354+
return { ratio, pass: ratio >= THRESHOLD };
355+
356+
};
357+
294358
/**
295359
* Sets the red component of a color.
296360
*

0 commit comments

Comments
 (0)