art
Version:
Cross-browser Vector Graphics
221 lines (171 loc) • 6.64 kB
JavaScript
var colors = {
maroon: '#800000', red: '#ff0000', orange: '#ffA500', yellow: '#ffff00', olive: '#808000',
purple: '#800080', fuchsia: "#ff00ff", white: '#ffffff', lime: '#00ff00', green: '#008000',
navy: '#000080', blue: '#0000ff', aqua: '#00ffff', teal: '#008080',
black: '#000000', silver: '#c0c0c0', gray: '#808080'
};
var map = function(array, fn){
var results = [];
for (var i = 0, l = array.length; i < l; i++)
results[i] = fn(array[i], i);
return results;
};
var Color = function(color, type){
if (color.isColor){
this.red = color.red;
this.green = color.green;
this.blue = color.blue;
this.alpha = color.alpha;
} else {
var namedColor = colors[color];
if (namedColor){
color = namedColor;
type = 'hex';
}
switch (typeof color){
case 'string': if (!type) type = (type = color.match(/^rgb|^hsb|^hsl/)) ? type[0] : 'hex'; break;
case 'object': type = type || 'rgb'; color = color.toString(); break;
case 'number': type = 'hex'; color = color.toString(16); break;
}
color = Color['parse' + type.toUpperCase()](color);
this.red = color[0];
this.green = color[1];
this.blue = color[2];
this.alpha = color[3];
}
this.isColor = true;
};
var limit = function(number, min, max){
return Math.min(max, Math.max(min, number));
};
var listMatch = /([-.\d]+\%?)\s*,\s*([-.\d]+\%?)\s*,\s*([-.\d]+\%?)\s*,?\s*([-.\d]*\%?)/;
var hexMatch = /^#?([a-f0-9]{1,2})([a-f0-9]{1,2})([a-f0-9]{1,2})([a-f0-9]{0,2})$/i;
Color.parseRGB = function(color){
return map(color.match(listMatch).slice(1), function(bit, i){
if (bit) bit = parseFloat(bit) * (bit[bit.length - 1] == '%' ? 2.55 : 1);
return (i < 3) ? Math.round(((bit %= 256) < 0) ? bit + 256 : bit) : limit(((bit === '') ? 1 : Number(bit)), 0, 1);
});
};
Color.parseHEX = function(color){
if (color.length == 1) color = color + color + color;
return map(color.match(hexMatch).slice(1), function(bit, i){
if (i == 3) return (bit) ? parseInt(bit, 16) / 255 : 1;
return parseInt((bit.length == 1) ? bit + bit : bit, 16);
});
};
Color.parseHSB = function(color){
var hsb = map(color.match(listMatch).slice(1), function(bit, i){
if (bit) bit = parseFloat(bit);
if (i === 0) return Math.round(((bit %= 360) < 0) ? (bit + 360) : bit);
else if (i < 3) return limit(Math.round(bit), 0, 100);
else return limit(((bit === '') ? 1 : Number(bit)), 0, 1);
});
var a = hsb[3];
var br = Math.round(hsb[2] / 100 * 255);
if (hsb[1] == 0) return [br, br, br, a];
var hue = hsb[0];
var f = hue % 60;
var p = Math.round((hsb[2] * (100 - hsb[1])) / 10000 * 255);
var q = Math.round((hsb[2] * (6000 - hsb[1] * f)) / 600000 * 255);
var t = Math.round((hsb[2] * (6000 - hsb[1] * (60 - f))) / 600000 * 255);
switch (Math.floor(hue / 60)){
case 0: return [br, t, p, a];
case 1: return [q, br, p, a];
case 2: return [p, br, t, a];
case 3: return [p, q, br, a];
case 4: return [t, p, br, a];
default: return [br, p, q, a];
}
};
Color.parseHSL = function(color){
var hsb = map(color.match(listMatch).slice(1), function(bit, i){
if (bit) bit = parseFloat(bit);
if (i === 0) return Math.round(((bit %= 360) < 0) ? (bit + 360) : bit);
else if (i < 3) return limit(Math.round(bit), 0, 100);
else return limit(((bit === '') ? 1 : Number(bit)), 0, 1);
});
var h = hsb[0] / 60;
var s = hsb[1] / 100;
var l = hsb[2] / 100;
var a = hsb[3];
var c = (1 - Math.abs(2 * l - 1)) * s;
var x = c * (1 - Math.abs(h % 2 - 1));
var m = l - c / 2;
var p = Math.round((c + m) * 255);
var q = Math.round((x + m) * 255);
var t = Math.round((m) * 255);
switch (Math.floor(h)){
case 0: return [p, q, t, a];
case 1: return [q, p, t, a];
case 2: return [t, p, q, a];
case 3: return [t, q, p, a];
case 4: return [q, t, p, a];
default: return [p, t, q, a];
}
};
var toString = function(type, array){
if (array[3] != 1) type += 'a';
else array.pop();
return type + '(' + array.join(', ') + ')';
};
Color.prototype = {
toHSB: function(array){
var red = this.red, green = this.green, blue = this.blue, alpha = this.alpha;
var max = Math.max(red, green, blue), min = Math.min(red, green, blue), delta = max - min;
var hue = 0, saturation = (delta != 0) ? delta / max : 0, brightness = max / 255;
if (saturation){
var rr = (max - red) / delta, gr = (max - green) / delta, br = (max - blue) / delta;
hue = (red == max) ? br - gr : (green == max) ? 2 + rr - br : 4 + gr - rr;
if ((hue /= 6) < 0) hue++;
}
var hsb = [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100), alpha];
return (array) ? hsb : toString('hsb', hsb);
},
toHSL: function(array){
var red = this.red, green = this.green, blue = this.blue, alpha = this.alpha;
var max = Math.max(red, green, blue), min = Math.min(red, green, blue), delta = max - min;
var hue = 0, saturation = (delta != 0) ? delta / (255 - Math.abs((max + min) - 255)) : 0, lightness = (max + min) / 512;
if (saturation){
var rr = (max - red) / delta, gr = (max - green) / delta, br = (max - blue) / delta;
hue = (red == max) ? br - gr : (green == max) ? 2 + rr - br : 4 + gr - rr;
if ((hue /= 6) < 0) hue++;
}
var hsl = [Math.round(hue * 360), Math.round(saturation * 100), Math.round(lightness * 100), alpha];
return (array) ? hsl : toString('hsl', hsl);
},
toHEX: function(array){
var a = this.alpha;
var alpha = ((a = Math.round((a * 255)).toString(16)).length == 1) ? a + a : a;
var hex = map([this.red, this.green, this.blue], function(bit){
bit = bit.toString(16);
return (bit.length == 1) ? '0' + bit : bit;
});
return (array) ? hex.concat(alpha) : '#' + hex.join('') + ((alpha == 'ff') ? '' : alpha);
},
toRGB: function(array){
var rgb = [this.red, this.green, this.blue, this.alpha];
return (array) ? rgb : toString('rgb', rgb);
}
};
Color.prototype.toString = Color.prototype.toRGB;
Color.hex = function(hex){
return new Color(hex, 'hex');
};
if (this.hex == null) this.hex = Color.hex;
Color.hsb = function(h, s, b, a){
return new Color([h || 0, s || 0, b || 0, (a == null) ? 1 : a], 'hsb');
};
if (this.hsb == null) this.hsb = Color.hsb;
Color.hsl = function(h, s, l, a){
return new Color([h || 0, s || 0, l || 0, (a == null) ? 1 : a], 'hsl');
};
if (this.hsl == null) this.hsl = Color.hsl;
Color.rgb = function(r, g, b, a){
return new Color([r || 0, g || 0, b || 0, (a == null) ? 1 : a], 'rgb');
};
if (this.rgb == null) this.rgb = Color.rgb;
Color.detach = function(color){
color = new Color(color);
return [Color.rgb(color.red, color.green, color.blue).toString(), color.alpha];
};
module.exports = Color;