/* global Color */ /* eslint no-unused-vars: off */ /** * Color Calculations. * * @since Twenty Twenty 1.0 * * @param {string} backgroundColor - The background color. * @param {number} accentHue - The hue for our accent color. * * @return {Object} - this */ function _twentyTwentyColor( backgroundColor, accentHue ) { // Set the object properties. this.backgroundColor = backgroundColor; this.accentHue = accentHue; this.bgColorObj = new Color( backgroundColor ); this.textColorObj = this.bgColorObj.getMaxContrastColor(); this.textColor = this.textColorObj.toCSS(); this.isDark = 0.5 > this.bgColorObj.toLuminosity(); this.isLight = ! this.isDark; // Return the object. return this; } /** * Builds an array of Color objects based on the accent hue. * For improved performance we only build half the array * depending on dark/light background-color. * * @since Twenty Twenty 1.0 * * @return {Object} - this */ _twentyTwentyColor.prototype.setAccentColorsArray = function() { var self = this, minSaturation = 65, maxSaturation = 100, minLightness = 30, maxLightness = 80, stepSaturation = 2, stepLightness = 2, pushColor = function() { var colorObj = new Color( { h: self.accentHue, s: s, l: l } ), item, /** * Get a score for this color in contrast to its background color and surrounding text. * * @since Twenty Twenty 1.0 * * @param {number} contrastBackground - WCAG contrast with the background color. * @param {number} contrastSurroundingText - WCAG contrast with surrounding text. * @return {number} - 0 is best, higher numbers have bigger difference with the desired scores. */ getScore = function( contrastBackground, contrastSurroundingText ) { var diffBackground = ( 7 >= contrastBackground ) ? 0 : 7 - contrastBackground, diffSurroundingText = ( 3 >= contrastSurroundingText ) ? 0 : 3 - contrastSurroundingText; return diffBackground + diffSurroundingText; }; item = { color: colorObj, contrastBackground: colorObj.getDistanceLuminosityFrom( self.bgColorObj ), contrastText: colorObj.getDistanceLuminosityFrom( self.textColorObj ) }; // Check a minimum of 4.5:1 contrast with the background and 3:1 with surrounding text. if ( 4.5 > item.contrastBackground || 3 > item.contrastText ) { return; } // Get a score for this color by multiplying the 2 contrasts. // We'll use that to sort the array. item.score = getScore( item.contrastBackground, item.contrastText ); self.accentColorsArray.push( item ); }, s, l, aaa; this.accentColorsArray = []; // We're using `for` loops here because they perform marginally better than other loops. for ( s = minSaturation; s <= maxSaturation; s += stepSaturation ) { for ( l = minLightness; l <= maxLightness; l += stepLightness ) { pushColor( s, l ); } } // Check if we have colors that are AAA compliant. aaa = this.accentColorsArray.filter( function( color ) { return 7 <= color.contrastBackground; } ); // If we have AAA-compliant colors, always prefer them. if ( aaa.length ) { this.accentColorsArray = aaa; } // Sort colors by contrast. this.accentColorsArray.sort( function( a, b ) { return a.score - b.score; } ); return this; }; /** * Get accessible text-color. * * @since Twenty Twenty 1.0 * * @return {Color} - Returns a Color object. */ _twentyTwentyColor.prototype.getTextColor = function() { return this.textColor; }; /** * Get accessible color for the defined accent-hue and background-color. * * @since Twenty Twenty 1.0 * * @return {Color} - Returns a Color object. */ _twentyTwentyColor.prototype.getAccentColor = function() { var fallback; // If we have colors returns the 1st one - it has the highest score. if ( this.accentColorsArray[0] ) { return this.accentColorsArray[0].color; } // Fallback. fallback = new Color( 'hsl(' + this.accentHue + ',75%,50%)' ); return fallback.getReadableContrastingColor( this.bgColorObj, 4.5 ); }; /** * Return a new instance of the _twentyTwentyColor object. * * @since Twenty Twenty 1.0 * * @param {string} backgroundColor - The background color. * @param {number} accentHue - The hue for our accent color. * @return {Object} - this */ function twentyTwentyColor( backgroundColor, accentHue ) {// jshint ignore:line var color = new _twentyTwentyColor( backgroundColor, accentHue ); color.setAccentColorsArray(); return color; }