@@ -28,6 +28,7 @@ import {
2828
2929 P3
3030} from 'colorjs.io/fn' ;
31+
3132import HSBSpace from './color_spaces/hsb.js' ;
3233
3334const map = ( n , start1 , stop1 , start2 , stop2 , clamp ) => {
@@ -41,6 +42,17 @@ const map = (n, start1, stop1, start2, stop2, clamp) => {
4142
4243const 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+
4456class 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