Show:

File: ia\utils\Color.js

/** 
 * The <code>Color</code> class is an all-static class with methods for working with colors. 
 * You do not create instances of <code>Color</code> instead you simply call static methods 
 * such as the <code>Color.getRandomColor()</code> method.
 * 
 * <p>All colors must use the format #<i>RRGGBB</i>. <i>RR</i>, <i>GG</i>, and <i>BB</i> 
 * each consist of two hexadecimal digits that specify the offset of each color component.</p>
 *
 * @author J Clare
 * @class ia.Color
 * @constructor
 */
ia.Color = function() {};

/**
 * Returns the red component of a color value.
 * 
 * @static
 * @method r
 * @param {String} c The color value.
 * @return  {String} The red component.
 */
ia.Color.r = function(c)
{
	var r;
	if (ia.Color.isHSV(c))
		r = ia.parseInt((ia.Color.cutRgb(ia.Color.HSVtoRGB(c)))[0]);
	else if (ia.Color.isHex(c))
		r = ia.parseInt((ia.Color.cutHex(c)).substring(0,2),16);
	else if (ia.Color.isRGB(c))
		r = ia.parseInt((ia.Color.cutRgb(c))[0]);
	return r;
};

/**
 * Returns the green component of a color value.
 * 
 * @static
 * @method g
 * @param {String} c The color value.
 * @return {String} The green component.
 */
ia.Color.g = function(c)
{
	var g;
	if (ia.Color.isHSV(c))
		g = ia.parseInt((ia.Color.cutRgb(ia.Color.HSVtoRGB(c)))[1]);
	else if (ia.Color.isHex(c))
		g = ia.parseInt((ia.Color.cutHex(c)).substring(2,4),16);
	else if (ia.Color.isRGB(c))
		g = ia.parseInt((ia.Color.cutRgb(c))[1]);
	return g;
};

/**
 * Returns the blue component of a color value.
 * 
 * @static
 * @method b
 * @param {String} c The color value
 * @return {String} The blue component
 */
ia.Color.b = function(c)
{
	var b;
	if (ia.Color.isHSV(c))
		b = ia.parseInt((ia.Color.cutRgb(ia.Color.HSVtoRGB(c)))[2]);
	else if (ia.Color.isHex(c))
		b = ia.parseInt((ia.Color.cutHex(c)).substring(4,6),16);
	else if (ia.Color.isRGB(c))
		b = ia.parseInt((ia.Color.cutRgb(c))[2]);
	return b;	
};

/**
 * Returns the alpha component of a color value.
 * 
 * @static
 * @method a
 * @param {String} c The color value.
 * @return {String} The alpha component.
 */
ia.Color.a = function(c)
{
	var a;
	if (ia.Color.isHSV(c))
		a = parseFloat(c[3]);
	else if (ia.Color.isHex(c))
		a = parseFloat((ia.Color.cutHex(c)).substring(6,8),16);
	else if (ia.Color.isRGB(c))
		a = parseFloat((ia.Color.cutRgb(c))[3]);
	return a;
};

/**
 * Returns the hue component of a color value.
 * 
 * @static
 * @method h
 * @param {String} c The color value.
 * @return  {String} The hue component 0 - 360.
 */
ia.Color.h = function(c)
{
	return ia.Color.toHSVA(c)[0];
};

/**
 * Returns the saturation component of a color value.
 * 
 * @static
 * @method s
 * @param {String} c The color value.
 * @return  {String} The hue component 0 - 100.
 */
ia.Color.s = function(c)
{
	return ia.Color.toHSVA(c)[1];
};

/**
 * Returns the value component of a color value.
 * 
 * @static
 * @method v
 * @param {String} c The color value.
 * @return  {String} The hue component 0 - 100.
 */
ia.Color.v = function(c)
{
	return ia.Color.toHSVA(c)[2];
};

/**
 * Returns a color value with the given red, green, blue, and alpha
 * components.
 * 
 * @static
 * @method toRGBA
 * @param {String} c A string of the form "rgb(25,90,127)" or "#FFFFFF".
 * @param {Number} alpha The alpha value 0 to 1.
 * @return {String} A string of the form "rgb(25,90,127, 0.1)".
 */
ia.Color.toRGBA = function(c, alpha)
{
	var a = alpha;
	if (a === undefined) a = 1;
	var r = ia.Color.r(c);
	var g = ia.Color.g(c);
	var b = ia.Color.b(c);
	return ia.Color.rgba(r, g, b, a);
};

/**
 * Returns a color value for a given string. 
 * Checks if the color is hex. If it is hex
 * the hex value is simply returned. If its
 * is rgb it is converted into hex and returned
 * 
 * @static
 * @method toHex
 * @param {String} c A string of the form "rgb(25,90,127)" or "#FFFFFF".
 * @return {String} The hex color value or 0.
 */
ia.Color.toHex = function(c)
{
	var r = ia.Color.r(c);
	var g = ia.Color.g(c);
	var b = ia.Color.b(c);
	var hex = "#"+ia.Color.intToHex(r)+ia.Color.intToHex(g)+ia.Color.intToHex(b);
	return hex;
};

/**
 * Returns a color value with the given hue, saturation, value, and alpha
 * components.
 * 
 * @static
 * @method toHSVA
 * @param {String} c A string of the form "rgb(25,90,127)" or "#FFFFFF".
 * @param {Number} alpha The alpha value 0 to 1.
 * @return {String} An of the form "[255,100,100,1]" - "[h,s,v,a]".
 */
ia.Color.toHSVA = function(c, alpha)
{
	var r = ia.Color.r(c);
	var g = ia.Color.g(c);
	var b = ia.Color.b(c);

	var h, s, v;
	var max = Math.max(r, g, b);
	var min = Math.min(r, g, b);

	if ( max === min ) h = 0;
	else if ( max === r ) h = ( 60 * (g - b) / ( max - min ) + 360 ) % 360;
	else if ( max === g ) h = 60 * ( b - r ) / ( max - min ) + 120;
	else if ( max === b ) h = 60 * ( r - g ) / ( max - min ) + 240;

	if ( max === 0 ) s = 0;
	else  s = (1 - min / max) * 100;

	v = (max / 255) * 100;

	return [h, s, v, alpha];
};

/**
 * Converts HSV to RGB.
 * 
 * @static
 * @method HSVtoRGB
 * @param {String} c An array of the form "[h, s, v, a]".
 * @return {String} A string of the form "rgb(25,90,127, 0.1)".
 */
ia.Color.HSVtoRGB = function(c)
{
	var h = c[0];
	var s = c[1] / 100;
	var v = (c[2] / 100) * 255;
	var a = c[3];

	if ( h < 0 ) { h += 360; }

	var hi = Math.floor( h / 60 ) % 6;
	var f = h / 60 - Math.floor( h / 60 );
	var p = v * (1 - s);
	var q = v * (1 - f * s);
	var t = v * (1 - ( 1 - f ) * s );
	var r, g, b;

	switch( hi ) 
	{
		case 0: 
			r = v;
			g = t;
			b = p;
		break;
		case 1: 
			r = q;
			g = v;
			b = p;
		break;
		case 2: 
			r = p;
			g = v;
			b = t;
		break;
		case 3: 
			r = p;
			g = q;
			b = v;
		break;
		case 4: 
			r = t;
			g = p;
			b = v;
		break;
		case 5: 
			r = v;
			g = p;
			b = q;
		break;
	}
	
	return ia.Color.rgba(r,g,b,a);
};

/** 
 * Validates a hex color.
 *
 * @static
 * @method validHex
 * @param {String} value The color.
 * @return {String} The validated value.
 */
ia.Color.validHex = function(value) 
{
	var value = value.replace(/[^#a-fA-F0-9]/g, ''); // non [#a-f0-9]
	value = value.toLowerCase();
	if(value.match(/#/g) && value.match(/#/g).length > 1) value = value.replace(/#/g, ''); // ##
	if(value.indexOf('#') === -1) value = '#'+value; // no #
	if(value.length > 7) value = value.substr(0,7); // too many chars
	return value;
};

/** 
 * Get the hexadecimal value of an integer.
 *
 * @static
 * @method intToHex
 * @param {Number} n The integer.
 * @return {String} The hexadecimal value.
 */
ia.Color.intToHex = function(n)
{
	if (n === null) return "00";
	n = ia.parseInt(n);
	if (n === 0 || isNaN(n)) return "00";
	n = Math.max(0,n);
	n = Math.min(n,255);
	n = Math.round(n);
	return "0123456789ABCDEF".charAt((n-n%16)/16) + "0123456789ABCDEF".charAt(n%16);
};

/** 
 * Get a hexadecimal colour with the hash removed.
 *
 * @static
 * @method cutHex
 * @param {String} c The color.
 * @return {String} The color.
 */
ia.Color.cutHex = function(c) {return (c.charAt(0)=="#") ? c.substring(1,7) : c;};

/** 
 * Get an rgb colour as an array.
 *
 * @static
 * @method cutRgb
 * @param {String} c The color.
 * @return {Array} An array.
 */
ia.Color.cutRgb = function(c)
{
	var cutRGB = c.substring(c.indexOf("(")+1,c.indexOf(")"));
	var rgbArray = cutRGB.split(",");
	return rgbArray;
};

/** 
 * Tests if the color is a hex.
 *
 * @static
 * @method isHex
 * @param {String} c The color.
 * @return {Boolean} true or false.
 */
ia.Color.isHex = function(c)
{
	return (c.indexOf("#") === 0);
};

/** 
 * Tests if the color is a rgb.
 *
 * @static
 * @method isRGB
 * @param {String} c The color.
 * @return {Boolean} true or false.
 */
ia.Color.isRGB = function(c)
{
	return (c.indexOf("rgb") !== -1);
};

/** 
 * Tests if the color is a hsv.
 *
 * @static
 * @method isHSV
 * @param {String} c The color.
 * @return {Boolean} true or false.
 */
ia.Color.isHSV = function(c)
{
	return (Object.prototype.toString.call(c) === '[object Array]');
};

/**
 * Returns a color value with the given red, green, blue, and alpha
 * components.
 * 
 * @static
 * @method rgba
 * @param {Number} r The red component (0-255).
 * @param {Number} g The green component (0-255).
 * @param {Number} b The blue component (0-255).
 * @param {Number} a The alpha component (0-1).
 * @return {String} The color value.
 */
ia.Color.rgba = function(r, g, b, a)
{
	if (a === undefined) a = 1;
	return "rgba("+Math.floor(r)+","+Math.floor(g)+","+Math.floor(b)+","+a+")";
};

/**
 * Interpolate between two color values by the given mixing proportion.
 * A mixing fraction of 0 will result in c1, a value of 1.0 will result
 * in c2, and value of 0.5 will result in the color mid-way between the
 * two in RGB color space.
 * 
 * @static
 * @method getInterpolatedColor
 * @param {String} c1 The starting color.
 * @param {String} c2 The target color.
 * @param {Number} f A fraction between 0 and 1 controlling the interpolation.
 * @return {String} The interpolated color.
 */
ia.Color.getInterpolatedColor = function(c1, c2, f)
{
	var t;
	return ia.Color.rgba(
		(t=ia.Color.r(c1)) + f*(ia.Color.r(c2)-t),
		(t=ia.Color.g(c1)) + f*(ia.Color.g(c2)-t),
		(t=ia.Color.b(c1)) + f*(ia.Color.b(c2)-t));
};

/** 
 * Returns a randomly generated color.
 * 
 * @static
 * @method getRandomColor
 * @return {String} The random color.
 */
ia.Color.getRandomColor = function()
{
	var r = Math.round(Math.random() * 255);
	var g = Math.round(Math.random() * 255);
	var b = Math.round(Math.random() * 255);
	return ia.Color.rgba(r,g,b);
};

/**
 * Lightens a color by the given percentage.
 * 
 * @static
 * @method lighten
 * @param {String} c The color.
 * @param {String} p The percentage as a fraction (0 - 1).
 * @return {String} The new color as a hex value.
 */
ia.Color.lighten = function(c, p) 
{
	var hsv = ia.Color.toHSVA(c); 

	var v= hsv[2];
	v = v + (v * p);
	if (v > 100) v = 100;
	if (v < 0) v = 0;
	hsv[2] = v;
	
	return ia.Color.toHex(hsv);
};

/**
 * Darkens a color by the given percentage.
 * 
 * @static
 * @method darken
 * @param {String} c The color.
 * @param {String} p The percentage as a fraction (0 - 1).
 * @return {String} The new color as a hex value.
 */
ia.Color.darken = function(c, p) 
{
	return ia.Color.lighten(c, (p*-1));
};

/**
 * Adjusts the saturation and value of the color.
 * 
 * @static
 * @method adjustSV
 * @param {String} c The color.
 * @param {String} s The saturation (0 - 100).
 * @param {String} v The value (0 - 100).
 * @return {String} The new color as a hex value.
 */
ia.Color.adjustSV = function(c, s, v) 
{
	var hsv = ia.Color.toHSVA(c); 
	hsv[1] = s;
	hsv[2] = v;
	return ia.Color.toHex(hsv);
};

/**
 * Saturates a color by the given percentage.
 * 
 * @static
 * @method saturate
 * @param {String} c The color.
 * @param {String} p The percentage as a fraction (0 - 1).
 * @return {String} The new color as a hex value.
 */
ia.Color.saturate = function(c, p) 
{
	var hsv = ia.Color.toHSVA(c); 

	var s = hsv[1];
	s = s + (s * p);
	if (s > 100) s = 100;
	if (s < 0) s = 0;
	hsv[1] = s;
	
	return ia.Color.toHex(hsv);
};

/**
 * desaturates a color by the given percentage.
 * 
 * @static
 * @method desaturate
 * @param {String} c The color.
 * @param {String} p The percentage as a fraction (0 - 1).
 * @return {String} The new color as a hex value.
 */
ia.Color.desaturate = function(c, p) 
{
	return ia.Color.saturate(c, (p*-1));
};

/** 
 * Shifts the hue by the given amount.
 * 
 * @static
 * @method hueShift
 * @param {Number} h The hue 0 - 360.
 * @param {Number} amount The amount 0 - 360.
 */
ia.Color.hueShift = function(h, amount) 
{
	h+=amount; 
	while (h>=360.0) h-=360.0; 
	while (h<0.0) h+=360.0; 
	return h; 
};

/** 
 * Returns a complementary color.
 * 
 * @static
 * @method complement
 * @param {String} c The color value.
 * @return {String} The complemetary color value.
 */
ia.Color.complement = function(c)
{
	var hsv = ia.Color.toHSVA(c); 
	var hue = hsv[0];
	hsv[0] = ia.Color.hueShift(hue,180.0);
	return ia.Color.toHex(hsv);
};

/** 
 * Returns an array containing the two triad colors.
 * 
 * @static
 * @method triad
 * @param {String} c The color value.
 * @return [String] The two triad colors.
 */
ia.Color.triad = function(c)
{
	var hsv = ia.Color.toHSVA(c); 
	var hue = hsv[0];
	var c1 = [ia.Color.hueShift(hue,180.0-24),hsv[1],hsv[2]];
	var c2 = [ia.Color.hueShift(hue,180.0+24),hsv[1],hsv[2]];
	return [ia.Color.toHex(c1),ia.Color.toHex(c2)];
};

/** 
 * Returns an array containing the two analogic colors.
 * 
 * @static
 * @method analogic
 * @param {String} c The color value.
 * @return [String] The two analogic colors.
 */
ia.Color.analogic = function(c)
{
	var hsv = ia.Color.toHSVA(c); 
	var hue = hsv[0];
	var c1 = [ia.Color.hueShift(hue,-24),hsv[1],hsv[2]];
	var c2 = [ia.Color.hueShift(hue,+24),hsv[1],hsv[2]];
	return [ia.Color.toHex(c1),ia.Color.toHex(c2)];
};