Skip to content

Instantly share code, notes, and snippets.

@dandean
Created August 12, 2009 21:37
Show Gist options
  • Save dandean/166783 to your computer and use it in GitHub Desktop.
Save dandean/166783 to your computer and use it in GitHub Desktop.
Represents a Color and can be converted into multiple formats
/**
* 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