5 * Contributor: Christian G. Höltje
7 * Licence: Public Domain
8 * Attribution is considered ethical, but not required.
11 * Color(255, 255, 255);
12 * Color(255, 255, 255, 1.0);
15 * Color("rgb(255, 255, 255)");
16 * Color("rgba(255, 255, 255, 1.0)");
17 * Color("white"); - CSS 2.1 Color keywords only
19 var Color = function() {
21 // CSS 2.1 Colour Keywords
42 // CSS Functional Notations and Hex Patterns
44 rgb : /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\);?$/,
45 "rgb%" : /^rgb\(\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\);?$/,
46 rgba : /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*((?:\d+(?:\.\d+)?)|(?:\.\d+))\s*\);?$/,
47 "rgba%" : /^rgba\(\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*((?:\d+(?:\.\d+)?)|(?:\.\d+))\s*\);?$/,
48 hex3 : /^#([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f]);?$/,
49 hex6 : /^#([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2});?$/
53 * Clamp the value between the low value and the high value
56 var clamp = function(value, low, high) {
60 else if (value > high) {
69 var alphaBlend = function(forground, background, alpha) {
70 return Math.round(background * (1.0 - alpha) + forground * (alpha));
74 * Return the colour in hexadecimal notation: #RRGGBB. e.g. #FF9933
75 * @param bg - Optional parameter used for calculating the colour if an alpha value less than 1.0 has been specified.
76 * If not specified, the alpha value will be ignored.
78 this.hex = function(bg) {
81 r = alphaBlend(this.red, bg.red, this.alpha);
82 g = alphaBlend(this.green, bg.green, this.alpha);
83 b = alphaBlend(this.blue, bg.blue, this.alpha);
90 var strHexR = r.toString(16).toUpperCase();
91 var strHexG = g.toString(16).toUpperCase();
92 var strHexB = b.toString(16).toUpperCase();
94 if (strHexR.length < 2) { strHexR = "0" + strHexR; }
95 if (strHexG.length < 2) { strHexG = "0" + strHexG; }
96 if (strHexB.length < 2) { strHexB = "0" + strHexB; }
98 return "#" + strHexR + strHexG + strHexB;
102 * Return the colour in CSS rgb() functional notation, using integers 0-255: rgb(255, 255 255);
103 * @param bg - Optional parameter used for calculating the colour if an alpha value less than 1.0 has been specified.
104 * If not specified, the alpha value will be ignored.
106 this.rgb = function(bg) {
109 r = alphaBlend(this.red, bg.red, this.alpha);
110 g = alphaBlend(this.green, bg.green, this.alpha);
111 b = alphaBlend(this.blue, bg.blue, this.alpha);
118 return "rgb(" + r + ", " + g + ", " + b + ")";
122 * Return the colour in CSS rgba() functional notation, using integers 0-255 for color components: rgb(255, 255 255, 1.0);
123 * @param bg - Optional parameter used for calculating the colour if an alpha value less than 1.0 has been specified.
124 * If not specified, and there is an alpha value, black will be used as the background colour.
126 this.rgba = function() {
127 return "rgba(" + this.red + ", " + this.green + ", " + this.blue + ", " + this.alpha + ")";
131 * Returns a Color object with the values inverted. Ignores alpha.
133 this.invert = function() {
134 return new Color("rgb(" +
135 (255 - this.red) + ", " +
136 (255 - this.green) + ", " +
137 (255 - this.blue) + ")");
141 * Blend this colour with the colour specified and return a pallet with all the steps in between.
142 * @param color - The colour to blend with
143 * @param steps - The number of steps to take to reach the color.
145 this.blend = function(color, steps) {
150 red : (alphaBlend(color.red, this.red, color.alpha) - this.red) / steps,
151 green : (alphaBlend(color.green, this.green, color.alpha) - this.green) / steps,
152 blue : (alphaBlend(color.blue, this.blue, color.alpha) - this.blue) / steps
154 for (i = 0; i < steps + 1; i++) {
155 r = Math.round(this.red + (step.red * i));
156 g = Math.round(this.green + (step.green * i));
157 b = Math.round(this.blue + (step.blue * i));
158 pallet.push(new Color(r, g, b));
164 * Constructor function
166 this.toString = this.hex;
169 var components, pattern;
172 if (arguments.length >= 3) {
173 /* r, g, b or r, g, b, a */
179 this.red = (!isNaN(r)) ? clamp(r, 0, 255) : 0;
180 this.green = (!isNaN(g)) ? clamp(g, 0, 255) : 0;
181 this.blue = (!isNaN(b)) ? clamp(b, 0, 255) : 0;
182 this.alpha = (!isNaN(a)) ? clamp(a, 0.0, 1.0) : 1.0;
183 } else if (arguments.length == 1) {
184 /* CSS Colour keyword or value */
185 value = keyword[arguments[0]] ? keyword[arguments[0]] : arguments[0];
188 if (func[key].test(value)) {
193 components = value.match(func[pattern]);
195 m = 1; // Multiplier for percentage values
208 components[1] = components[1] + "" + components[1];
209 components[2] = components[2] + "" + components[2];
210 components[3] = components[3] + "" + components[3];
217 components = [0, "255", "255", "255", "1.0"];
220 this.red = clamp(Math.round(parseInt(components[1],base) * m), 0, 255);
221 this.green = clamp(Math.round(parseInt(components[2],base) * m), 0, 255);
222 this.blue = clamp(Math.round(parseInt(components[3],base) * m), 0, 255);
224 if (isNaN(components[4])) {
227 this.alpha = clamp(parseFloat("0" + components[4]), 0.0, 1.0);