95 lines
2.7 KiB
JavaScript
95 lines
2.7 KiB
JavaScript
(function(tree) {
|
|
//
|
|
// RGB Colors - #ff0014, #eee
|
|
//
|
|
tree.Color = function Color(rgb, a) {
|
|
//
|
|
// The end goal here, is to parse the arguments
|
|
// into an integer triplet, such as `128, 255, 0`
|
|
//
|
|
// This facilitates operations and conversions.
|
|
//
|
|
if (Array.isArray(rgb)) {
|
|
this.rgb = rgb;
|
|
} else if (rgb.length == 6) {
|
|
this.rgb = rgb.match(/.{2}/g).map(function(c) {
|
|
return parseInt(c, 16);
|
|
});
|
|
} else {
|
|
this.rgb = rgb.split('').map(function(c) {
|
|
return parseInt(c + c, 16);
|
|
});
|
|
}
|
|
this.is = 'color';
|
|
this.alpha = typeof(a) === 'number' ? a : 1;
|
|
};
|
|
tree.Color.prototype = {
|
|
eval: function() { return this },
|
|
|
|
//
|
|
// If we have some transparency, the only way to represent it
|
|
// is via `rgba`. Otherwise, we use the hex representation,
|
|
// which has better compatibility with older browsers.
|
|
// Values are capped between `0` and `255`, rounded and zero-padded.
|
|
//
|
|
toString: function() {
|
|
if (this.alpha < 1.0) {
|
|
return 'rgba(' + this.rgb.map(function(c) {
|
|
return Math.round(c);
|
|
}).concat(this.alpha).join(', ') + ')';
|
|
} else {
|
|
return '#' + this.rgb.map(function(i) {
|
|
i = Math.round(i);
|
|
i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16);
|
|
return i.length === 1 ? '0' + i : i;
|
|
}).join('');
|
|
}
|
|
},
|
|
|
|
//
|
|
// Operations have to be done per-channel, if not,
|
|
// channels will spill onto each other. Once we have
|
|
// our result, in the form of an integer triplet,
|
|
// we create a new Color node to hold the result.
|
|
//
|
|
operate: function(op, other) {
|
|
var result = [];
|
|
|
|
if (! (other instanceof tree.Color)) {
|
|
other = other.toColor();
|
|
}
|
|
|
|
for (var c = 0; c < 3; c++) {
|
|
result[c] = tree.operate(op, this.rgb[c], other.rgb[c]);
|
|
}
|
|
return new tree.Color(result);
|
|
},
|
|
|
|
toHSL: function() {
|
|
var r = this.rgb[0] / 255,
|
|
g = this.rgb[1] / 255,
|
|
b = this.rgb[2] / 255,
|
|
a = this.alpha;
|
|
|
|
var max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
var h, s, l = (max + min) / 2, d = max - min;
|
|
|
|
if (max === min) {
|
|
h = s = 0;
|
|
} else {
|
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
|
|
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;
|
|
}
|
|
return { h: h * 360, s: s, l: l, a: a };
|
|
}
|
|
};
|
|
|
|
|
|
})(require('mess/tree'));
|