RGB
ビット演算を使ったコードサンプルなはずなのに arguments は透過的でなくて使いにくいとか zero padding は標準で提供すべきとか思ってしまった。あと RGB <--> HSV 変換式のわかりづらさは異常。コーディングしたもののうごかねー。
で、これがあると何がうれしいかって rgb それぞれと #xxxxxx 的な表現を指定する type="text" な input 要素や css で color / background-color をいじる JavaScript コードを組み合わせるとよくある色指定ツールができるはず。というか作ってしまった -> http://www012.upp.so-net.ne.jp/legio/color.html http://www012.upp.so-net.ne.jp/legio/colortest/ 。おいィ !? センスが微塵も感じられないんだが ?
// for RGB function RGB() { this.initialize.apply(this, arguments); } RGB.prototype = { initialize: function () { this.errmsg = 'you can assign Array that have more than 3 vlaues or string look like RGB value'; if (arguments.length === 1) this.set(arguments[0]); else if (arguments.length === 3) this.set(arguments[0], arguments[1], arguments[2]); else throw new Error(this.errmsg); }, range: function (n) { if (0 <= n && n < 256) return n; else throw new Error('each RGB value must be integer and lesser than 256'); }, set: function () { if (arguments.length === 3) { this.r = this.range(arguments[0]); this.g = this.range(arguments[1]); this.b = this.range(arguments[2]); return; } else if (arguments.length !== 1) throw new Error(this.errmsg); var rgb = arguments[0]; switch (typeof rgb) { case 'object': if (rgb instanceof Array && rgb.length >= 3) { this.r = this.range(rgb[0]); this.g = this.range(rgb[1]); this.b = this.range(rgb[2]); return; } else throw new Error(this.errmsg); break; case 'number': { rgb = rgb.toString(16); var l = rgb.length, t = []; if (l <= 3) rgb = this.zeroPadding(rgb, 3); else if (l <= 6) rgb = this.zeroPadding(rgb, 6); else throw new Error(this.errmsg); } case 'string': if (/^#?([0-f]{3})$/.test(rgb)) { var n = parseInt(RegExp.$1, 16); this.r = (n & 0xf00) >> 4; // >> 8 << 4 this.g = (n & 0x0f0); // >> 4 << 4 this.b = (n & 0x00f) << 4; // << 4 return; } if (/^#?([0-f]{6})$/.test(rgb)) { var n = parseInt(RegExp.$1, 16); this.r = (n & 0xff0000) >> 16; this.g = (n & 0x00ff00) >> 8; this.b = n & 0x0000ff; return; } throw new Error(this.errmsg); default: throw new Error(this.errmsg); } }, toNumber: function () (this.r << 16) | (this.g << 8) | this.b, toString: function () '#' + this.zeroPadding(this.toNumber().toString(16), 6), get red() this.r, get green() this.g, get blue() this.b, zeroPadding: function (str, digit) { var z = [], l = str.length; for (var i=0, m=digit-l ; i<m ; ++i) z.push('0'); return z.join('') + str; }, // refer: http://ja.wikipedia.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93 // not work!! toHSV: function () { var max = Math.max(this.r, this.g, this.b); var min = Math.min(this.r, this.g, this.b); if (max === 0) return new HSV(0, 0, 0); var sub = max - min; var v = max; var s = Math.ceil(255 * sub / max); var h; if (sub) { switch (max) { case this.r: h = 60 * ((this.b - this.g) / sub); break; case this.g: h = 60 * (2 + (this.r - this.b) / sub); break; case this.b: h = 60 * (4 + (this.g - this.r) / sub); break; default: throw new Error('naiwa-'); } h = Math.ceil(h); while (h < 0) h += 360; } else { h = 0; } return new HSV(h, s, v); }, }; // for HSV function HSV() { this.initialize.apply(this, arguments); } HSV.prototype = { initialize: function (h, s, v) { this.set(h, s, v); }, set: function (h, s, v) { this.h = h; this.s = s; this.v = v; }, // refer: http://ja.wikipedia.org/wiki/HSV%E8%89%B2%E7%A9%BA%E9%96%93 // not work!! toRGB: function () { if (this.s === 0) return new RGB(0, 0 ,0); var ht = this.h / 60; var st = this.s / 255; var hi = Math.ceil(ht) % 6; var f = ht - hi; var m = Math.ceil(this.v * (1 - st)); var n = Math.ceil(this.v * (1 - st * f)); var k = Math.ceil(this.v * (1 - st * (1 - f))); if (m > 255) m = 255; if (n > 255) n = 255; if (k > 255) k = 255; if (m < 0) m = 0; if (n < 0) n = 0; if (k < 0) k = 0; liberator.log([m,n,k], 0); switch (hi) { case 0: return new RGB(this.v, k, m); case 1: return new RGB(n, this.v, m); case 2: return new RGB(m, this.v, k); case 3: return new RGB(m, n, this.v); case 4: return new RGB(k, m, this.v); case 5: return new RGB(this.v, m, n); } }, get hue() this.h, get saturation() this.s, get brightness() this.v, };