Created
August 12, 2009 21:37
-
-
Save dandean/166783 to your computer and use it in GitHub Desktop.
Represents a Color and can be converted into multiple formats
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* class Color | |
**/ | |
var Color = Class.create((function() { | |
function _testFormatSupport(format) { | |
var el = document.createElement("span"); | |
var oldColor = el.style.color = "red"; | |
try { | |
el.style.color = format; | |
} catch (e) {} | |
return el.style.color != oldColor; | |
} | |
var SUPPORTS_RGB = _testFormatSupport("rgb(0,0,0)"), | |
SUPPORTS_RGBA = (SUPPORTS_RGB && _testFormatSupport("rgba(0,0,0,0)")); | |
return { | |
/** | |
* new Color(); | |
Methods store data in "data" object | |
Instantions convert into rgba automatically | |
If data doesn't exist for method, convert from RGB, store it, return it. | |
**/ | |
initialize: function() { | |
this.data = {}; | |
}, | |
css: function() { | |
var o = this.rgbaObject(); | |
if (SUPPORTS_RGBA) return this.rgbaCss(); | |
if (o.a == 0) return "transparent"; | |
if (SUPPORTS_RGB) return this.rgbCss(); | |
return hex(); | |
}, | |
rgb: function() { | |
if (!("rgb" in this.data)) { | |
var o = this.rgbaObject(); | |
this.data.rgb = [o.r, o.g, o.b].join(","); | |
} | |
return this.data.rgb; | |
}, | |
rgbCss: function() { | |
if (!("rgbCss" in this.data)) this.data.rgbCss = ("rgb(" + this.rgb() + ")"); | |
return this.data.rgbCss; | |
}, | |
rgba: function() { | |
if (!("rgba" in this.data)) { | |
var o = this.rgbaObject(); | |
this.data.rgba = [o.r, o.g, o.b, o.a].join(","); | |
} | |
return this.data.rgba; | |
}, | |
rgbaCss: function() { | |
if (!("rgbaCss" in this.data)) this.data.rgbaCss = ("rgba(" + this.rgba() + ")"); | |
return this.data.rgbaCss; | |
}, | |
rgbaObject: function() { | |
// Defaults to black transparent. | |
if (!("rgbaObject" in this.data)) this.data.rgbaObject = {r: 0, g: 0, b: 0, a: 0}; | |
return this.data.rgbaObject; | |
}, | |
hex: function() { | |
if (!("hex" in this.data)) { | |
var o = this.rgbaObject(); | |
this.data.hex = "#" + o.r.toColorPart() + o.g.toColorPart() + o.b.toColorPart(); | |
} | |
return this.data.hex; | |
}, | |
/** | |
* Color#hsv() -> Object | |
* Returns on object with `h`, `s` and `v` properties. | |
**/ | |
hsv: function() { | |
if (!("hsv" in this.data)) { | |
var o = this.rgbaObject(), | |
r = o.r/255, | |
g = o.g/255, | |
b = o.b/255, | |
max = Math.max(r, g, b), | |
min = Math.min(r, g, b), | |
h, s, v = max, | |
d = max - min; | |
s = max == 0 ? 0 : d / max; | |
if (max == min) { | |
h = 0; // achromatic | |
} else { | |
switch (max) { | |
case r: h = (g - b) / d + (g < b ? 6 : 0); break; | |
case g: h = (b - r) / d + 2; break; | |
case b: h = (r - g) / d + 4; break; | |
} | |
h /= 6; | |
} | |
this.data.hsv = {h:h, s:s, v:v}; | |
} | |
return this.data.hsv; | |
}, | |
inspect: function() { | |
return "#<Color: " + this.rgba() + ">"; | |
}, | |
toString: function() { return "[object Color]"; } | |
}; | |
})()); | |
Object.extend(Color, (function() { | |
function _hsvToRgba(h, s, v) { | |
var r, g, b; | |
var i = Math.floor(h * 6); | |
var f = h * 6 - i; | |
var p = v * (1 - s); | |
var q = v * (1 - f * s); | |
var t = v * (1 - (1 - f) * s); | |
switch(i % 6){ | |
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 {r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255), a: 1}; | |
} | |
function _hexToRgba(hex) { | |
return { | |
r: parseInt(hex.substring(0,2), 16), | |
g: parseInt(hex.substring(2,4), 16), | |
b: parseInt(hex.substring(4,6), 16), | |
a: 1 | |
}; | |
} | |
return { | |
TryParse: function(value) { | |
if (Object.isString(value)) { | |
var match; | |
if (value.match(/^(#)?[a-z0-9]{3}$/i) || value.match(/^(#)?[a-z0-9]{6}$/i)) { // From 3 or 6 hex | |
return Color.Hex(value); | |
} else if ((value.match(/\d+/g) || []).length >= 3) { // any RGB(A) format | |
return Color.RGB(value); | |
} | |
} | |
// return transparent color by default. | |
var color = new Color(); | |
return color; | |
}, | |
/** | |
* Color.RGB(value1[, value2, value3[, alpha = 1]]) -> Color | |
* | |
* Creates a color object out of a single string or individual rgba values. | |
**/ | |
RGB: function(red, green, blue, alpha) { | |
var rgba = {}, value = red; | |
if (arguments.length == 1) { | |
// Parse out of string... | |
var match = (value || "").match(/\d+/g); | |
if (!match || match.length < 3) throw 'Color.RGB, "Invalid Argument."'; | |
rgba = { | |
r: parseInt(match[0]) || 0, | |
g: parseInt(match[1]) || 0, | |
b: parseInt(match[2]) || 0, | |
a: (typeof match[3] == "string") ? parseFloat(match[3]) : 1 | |
}; | |
} else if (arguments.length >= 3) { | |
rgba = {r: red, g: green, b: blue, a: (typeof alpha == "undefined") ? 1 : parseFloat(alpha) }; | |
} else throw 'Color.RGB, "Invalid Argument."'; | |
var color = new Color(); | |
color.data.rgbaObject = rgba; | |
return color; | |
}, | |
Hex: function(value) { | |
if (!Object.isString(value)) throw 'Color.Hex, "Invalid argument."'; | |
value = value.replace("#",""); | |
if (value.match(/^[a-z0-9]{3}$/i)) { // From short HEX 3 | |
value = value[0] + value[0] + value[1] + value[1] + value[2] + value[2]; | |
} | |
if (value.match(/^[a-z0-9]{6}$/i)) { // From long HEX 6 | |
var color = new Color(); | |
color.data.hex = "#" + value; | |
color.data.rgbaObject = _hexToRgba(value); | |
return color; | |
} | |
throw 'Color#Hex, "Invalid argument, value is not in HEX format."'; | |
}, | |
HSV: function(h, s, v) { | |
if (arguments.length != 3) throw 'Color.HSV, "Invalid arguments."'; | |
var color = new Color(); | |
color.data.hsv = {h:h, s:s, v:v}; | |
color.data.rgbaObject = _hsvToRgba(h, s, v); | |
return color; | |
} | |
}; | |
})()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment