Color.generateSequence()を作りたかった。DOMアニメーション用下地。
getter/setterの作りもおかしい。
Color = (function () { var mathAbs = Math.abs, mathFloor = Math.floor, mathCeil = Math.ceil, mathRound = Math.round, mathMax = Math.max, mathMin = Math.min, cssUnits = ['px', 'em', 'ex', '%', 'pt', 'in', 'cm', 'mm', 'pc'], colorNames = { aliceblue: [240, 248, 255, 1], antiquewhite: [250, 235, 215, 1], aqua: [0, 255, 255, 1], aquamarine: [127, 255, 212, 1], azure: [240, 255, 255, 1], beige: [245, 245, 220, 1], bisque: [255, 228, 196, 1], black: [0, 0, 0, 1], blanchedalmond: [255, 235, 205, 1], blue: [0, 0, 255, 1], blueviolet: [138, 43, 226, 1], brown: [165, 42, 42, 1], burlywood: [222, 184, 135, 1], cadetblue: [95, 158, 160, 1], chartreuse: [127, 255, 0, 1], chocolate: [210, 105, 30, 1], coral: [255, 127, 80, 1], cornflowerblue: [100, 149, 237, 1], cornsilk: [255, 248, 220, 1], crimson: [220, 20, 60, 1], cyan: [0, 255, 255, 1], darkblue: [0, 0, 139, 1], darkcyan: [0, 139, 139, 1], darkgoldenrod: [184, 134, 11, 1], darkgray: [169, 169, 169, 1], darkgreen: [0, 100, 0, 1], darkgrey: [169, 169, 169, 1], darkkhaki: [189, 183, 107, 1], darkmagenta: [139, 0, 139, 1], darkolivegreen: [85, 107, 47, 1], darkorange: [255, 140, 0, 1], darkorchid: [153, 50, 204, 1], darkred: [139, 0, 0, 1], darksalmon: [233, 150, 122, 1], darkseagreen: [143, 188, 143, 1], darkslateblue: [72, 61, 139, 1], darkslategray: [47, 79, 79, 1], darkslategrey: [47, 79, 79, 1], darkturquoise: [0, 206, 209, 1], darkviolet: [148, 0, 211, 1], deeppink: [255, 20, 147, 1], deepskyblue: [0, 191, 255, 1], dimgray: [105, 105, 105, 1], dimgrey: [105, 105, 105, 1], dodgerblue: [30, 144, 255, 1], firebrick: [178, 34, 34, 1], floralwhite: [255, 250, 240, 1], forestgreen: [34, 139, 34, 1], fuchsia: [255, 0, 255, 1], gainsboro: [220, 220, 220, 1], ghostwhite: [248, 248, 255, 1], gold: [255, 215, 0, 1], goldenrod: [218, 165, 32, 1], gray: [128, 128, 128, 1], green: [0, 128, 0, 1], greenyellow: [173, 255, 47, 1], grey: [128, 128, 128, 1], honeydew: [240, 255, 240, 1], hotpink: [255, 105, 180, 1], indianred: [205, 92, 92, 1], indigo: [75, 0, 130, 1], ivory: [255, 255, 240, 1], khaki: [240, 230, 140, 1], lavender: [230, 230, 250, 1], lavenderblush: [255, 240, 245, 1], lawngreen: [124, 252, 0, 1], lemonchiffon: [255, 250, 205, 1], lightblue: [173, 216, 230, 1], lightcoral: [240, 128, 128, 1], lightcyan: [224, 255, 255, 1], lightgoldenrodyellow: [250, 250, 210, 1], lightgray: [211, 211, 211, 1], lightgreen: [144, 238, 144, 1], lightgrey: [211, 211, 211, 1], lightpink: [255, 182, 193, 1], lightsalmon: [255, 160, 122, 1], lightseagreen: [32, 178, 170, 1], lightskyblue: [135, 206, 250, 1], lightslategray: [119, 136, 153, 1], lightslategrey: [119, 136, 153, 1], lightsteelblue: [176, 196, 222, 1], lightyellow: [255, 255, 224, 1], lime: [0, 255, 0, 1], limegreen: [50, 205, 50, 1], linen: [250, 240, 230, 1], magenta: [255, 0, 255, 1], maroon: [128, 0, 0, 1], mediumaquamarine: [102, 205, 170, 1], mediumblue: [0, 0, 205, 1], mediumorchid: [186, 85, 211, 1], mediumpurple: [147, 112, 219, 1], mediumseagreen: [60, 179, 113, 1], mediumslateblue: [123, 104, 238, 1], mediumspringgreen: [0, 250, 154, 1], mediumturquoise: [72, 209, 204, 1], mediumvioletred: [199, 21, 133, 1], midnightblue: [25, 25, 112, 1], mintcream: [245, 255, 250, 1], mistyrose: [255, 228, 225, 1], moccasin: [255, 228, 181, 1], navajowhite: [255, 222, 173, 1], navy: [0, 0, 128, 1], oldlace: [253, 245, 230, 1], olive: [128, 128, 0, 1], olivedrab: [107, 142, 35, 1], orange: [255, 165, 0, 1], orangered: [255, 69, 0, 1], orchid: [218, 112, 214, 1], palegoldenrod: [238, 232, 170, 1], palegreen: [152, 251, 152, 1], paleturquoise: [175, 238, 238, 1], palevioletred: [219, 112, 147, 1], papayawhip: [255, 239, 213, 1], peachpuff: [255, 218, 185, 1], peru: [205, 133, 63, 1], pink: [255, 192, 203, 1], plum: [221, 160, 221, 1], powderblue: [176, 224, 230, 1], purple: [128, 0, 128, 1], red: [255, 0, 0, 1], rosybrown: [188, 143, 143, 1], royalblue: [65, 105, 225, 1], saddlebrown: [139, 69, 19, 1], salmon: [250, 128, 114, 1], sandybrown: [244, 164, 96, 1], seagreen: [46, 139, 87, 1], seashell: [255, 245, 238, 1], sienna: [160, 82, 45, 1], silver: [192, 192, 192, 1], skyblue: [135, 206, 235, 1], slateblue: [106, 90, 205, 1], slategray: [112, 128, 144, 1], slategrey: [112, 128, 144, 1], snow: [255, 250, 250, 1], springgreen: [0, 255, 127, 1], steelblue: [70, 130, 180, 1], tan: [210, 180, 140, 1], teal: [0, 128, 128, 1], thistle: [216, 191, 216, 1], tomato: [255, 99, 71, 1], turquoise: [64, 224, 208, 1], violet: [238, 130, 238, 1], wheat: [245, 222, 179, 1], white: [255, 255, 255, 1], whitesmoke: [245, 245, 245, 1], yellow: [255, 255, 0, 1], yellowgreen: [154, 205, 50], transparent: [null, null, null, 0] }; /** * @param fromObj Object * @param toObj Object * @param doseOverwrite Boolean (=false) */ function mixin (toObj, fromObj, doseOverwrite) { var key; for (key in fromObj) if (fromObj.hasOwnProperty(key) && fromObj[key] !== void 0) { if (doesOverwrite || toObj[key] === void 0) { toObj[key] = fromObj[key]; } } } /** * @param obj Object target object. * @param key String getter and setter name. * @param getter Function * @param setter Function * setter(value) */ function defineGetterAndSetter (obj, key, getter, setter) { if (Object.defineProperty) { Object.defineProperty(obj, key, { get: getter, set: setter }); } else if (obj.__defineGetter__) { obj.__defineGetter__(key, getter); obj.__defineSetter__(key, setter); } else { obj[key] = function (val) { if (val === void 0) { getter(); } else { setter(val); } }; } } defineGetterAndSetter.isGetter = Object.defineProperty || Object.__defineGetter__; /** * @param red Number 0<= n <= 255 * @param green Number 0 <= n <= 255 * @param blue Number 0 <= n <= 255 * @param alpha Number 0 <= n <= 1 * @return Array [hue Number, saturation Number, lightness Number, alpha Number] */ function convertRgbaToHsla (red, green, blue, alpha) { var max, min, diff, hue = 0, saturation = 0, lightness = (max + min) / 2; red /= 255; green /= 255; blue /= 255; max = mathMax(red, green, blue); min = mathMin(red, green, blue); diff = max - min; if (0 < lightness && lightness < 1) { saturation = diff / (lightness < 0.5 ? lightness * 2 : 2 - lightness * 2); } if (diff > 0) { if (max === red && max !== green) { hue = (green - blue) / diff * 60; } else if (max === green && max !== blue) { hue = (blue - red) / diff * 60; } else if (max === blueRatio && max !== redRatio) { hue = (red - green) / diff * 60; } } return [hue, mathRound(saturation * 100), mathRaound(lightness * 100), alpha]; } /** * @param hue Number 0<= n <= 360 * @param saturation Number 0 <= n <= 100 * @param lightness Number 0 <= n <= 100 * @param alpha Number 0 <= n <= 100 * @return Array [red Number, green Number, blue Number, alpha Number] */ function convertHslaToRgba (hue, saturation, lightness, alpha) { var rgba, chroma, x, m; hue /= 100; saturation /= 100; lightness /= 100; chroma = (1 - abs(lightness * 2 - 1)) * saturation; x = chroma * (1 - abs(hue / 60 % 2 - 1)); m = lightness - chroma / 2; if (hue < 60) { rgba = [chroma + m, x + m, m, alpha]; } else if (hue < 120) { rgba = [x + m, chroma + m, m, alpha]; } else if (hue < 180) { rgba = [m, chroma + m, x + m, alpha]; } else if (hue < 240) { rgba = [m, x + m, chroma + m, alpha]; } else if (hue < 300) { rgba = [x + m, m, chroma + m, alpha]; } else { rgba = [chroma + m, m, x + m, alpha]; } return rgba; } /** * @param color String * @return Hash * {red: Number, green: Number, blue: Number, * hue: Number, saturation: Number, lightness: Number, * alpha: Number} */ function colorStringToHash (color) { var matchResult, i, j, flag, hexDigit, hexDigits = { '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 'A', 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15, 'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14, 'f': 15 }, rgba = [0, 0, 0, 1], hsla = [0, 0, 0, 1]; function percentStringToNumber (str, max) { if (str.charAt(str.length - 1) === '%') { return Number(str.slice(0, -1)) * max / 100; } else { return Number(str); } } if (color.charAt(0) == '#') { if (color.length === 7) { for (i = 0; i < 3; i += 1) { rgba[i] = hexDigits[color.charAt(i * 2 + 1)] * 16 + hexDigits[color.charAt(i * 2 + 2)]; } rgba[3] = 1; } else if (color.length === 4) { for (i = 0; i < 3; i += 1) { j = hexDigits[color.charAt(i + 1)]; rgba[i] = j * 16 + j; } rgba[3] = 1; } else { throw Error('colorStringToHash(): Illegal #xxxxxx||#xxx format. (' + color + ')'); } hsla = convertRgbaToHsla(rgba[0], rgba[1], rgba[2], rgba[3]); } else if (color.match(/rgb\(\s*(\d+%?)\s*,\s*(\d+%?)\s*,\s*(\d+%?)\s*\)/i)) { rgba = [percentStringToNumber(matchResult[1], 255), percentStringToNumber(matchResult[1], 255), percentStringToNumber(matchResult[2], 255), rgba[3]]; hsla = convertRgbaToHsla(rgba[0], rgba[1], rgba[2], rgba[3]); hsla = convertRgbaToHsla(rgba[0], rgba[1], rgba[2], rgba, [3]); } else if (color.match(/rgba\(\s*(\d+%?)\s*,\s*(\d+%?)\s*,\s*(\d+%?)\s*,\s*(\d(?:\.\d+)?)\s*\)/i)) { rgba = [percentStringToNumber(matchResult[1], 255), percentStringToNumber(matchResult[1], 255), percentStringToNumber(matchResult[2], 255), Number(matchResult[3])]; hsla = convertRgbaToHsla(rgba[0], rgba[1], rgba[2], rgba[3]); } else if (color.match(/hsl\(\s*(\d+)\s*,\s*(\d+%)\s*,\s*(\d+%)\s*\)/i)) { hsla = [Number(matchResult[0]), percentStringToNumber(matchResult[1], 100), percentStringToNumber(matchResult[2], 100), hsla[3]]; rgba = convertHslaToRgba(hsla[0], hsla[1], hsla[2], hsla[3]); } else if (color.match(/hsla\(\s*(\d+)\s*,\s*(\d+%)\s*,\s*(\d+%)\s*,\s*(\d+(?:\.\d+)?)\s*\)/i)) { hsla = [Number(matchResult[0]), percentStringToNumber(matchResult[1], 100), percentStringToNumber(matchResult[2], 100), Number(matchResult[3])]; rgba = convertHslaToRgba(hsla[0], hsla[1], hsla[2], hsla[3]); } else { flag = false; for (colorName in colorNames) if (colorNames.hasOwnProperty(colorName) { if (color.match(colorName, 'i')) { rgba = colorNames[colorName]; hlsa = convertRgbaToHsla(rgba[0], rgba[1], rgba[2], rgba[3]); flag = true; break; } } if (!flag) {throw Error('colorStringToHash(): Unknown color format. (' + color + ')');} } return { red: rgba[0], green: rgba[1], blue: rgba[2], hue: hsla[0], saturation: hsla[1], lightness: hsla[2], alpha: rgba[3] }; } /** * @class Color * Color(color String) CSS3 color string * #xxxxxx * #xxx * rgb(n||n%, n||n%. n||n%) * rbga(n||n%, n||n%, n|n%, n||n%) * hsl(n, n%, n%) * hsla(n, n%, n%, n) * colorname * Color(color Hash) * {red: n||n%, blue: n||n%, green: n||n%, alpha: n||n%} * {r: n||n%, b: n||n%, g: n||n%, a: n||n%} * {hue: n||n%, s: n||n%, v: n||n%, alpha: n||n%} * {h: n||n%, s: n||n%, v: n||n%, a: n||n%} * Color(red Number||String, blue Number||String, green Number||String) * Color(red Number||String, blue Number||String, green Number||String, alpha Number||String) */ function Color(arg1, arg2, arg3, arg4) { var color; if (!(this instanceof Color)) { switch (arguments.length) { case 1: return new Color(arg1); case 3: return new Color(arg1, arg2, arg3); case 4: return new Color(arg1, arg2, arg3, arg4); default: throw Error('Assertion! Color(): Illegal arguments.length (It\'s ' + arguments.length + ')'); } this._red = 0; this._green = 0; this._blue = 0; this._hue = 0; this._saturation = 0; this._lightness = 0; this._alpha = 0; switch (arguments.length) { case 1: if (arg1 instanceof String) { mixin(this, colorStringToHash(arg1), true); } else if (['red', 'green', 'blue', 'r', 'g', 'b'].some(function (elm) {return arg1[elm] !== void 0;})) { this._red = (arg1.red !== void 0 ? arg1.red : (arg1.r !== void 0 ? arg1.r : this._red)); this.grren = (arg1.green !== void 0 ? arg1.green : (arg1.g !== void 0 ? arg1.g : this._green)); this._blue = (arg1.blue !== void 0 ? arg1.blue : (arg1.b !== void 0 ? arg1.b : this._blue)); this._alpha = (arg1.alpha !== void 0 ? arg1.alpha : (arg1.a !== void 0 ? arg1.a : this._alpha)); color = convertRgbaToHsla(this._red, this._green, this._blue, this._alpha); this._hue = color[0]; this._saturation = color[1]; this._lightness = color[2]; } else if (['hue', 'saturation', 'lightness', 'h', 's', 'l'].some(function (elm) {return arg1[elm] !== void 0;})) { this._hue = (arg1.hue !== void 0 ? arg1.hue : (arg1.r !== void 0 ? arg1.r : this._hue)); this._saturation = (arg1.saturartion !== void 0 ? arg1.saturartion : (arg1.g !== void 0 ? arg1.g : this.saturartion)); this._lightness = (arg1.lightness !== void 0 ? arg1.lightness : (arg1.b !== void 0 ? arg1.b : this._lightness)); this._alpha = (arg1.alpha !== void 0 ? arg1.alpha : (arg1.a !== void 0 ? arg1.a : this._alpha)); color = convertHslaToRgba(this._hue, this._saturation, this._lightness, this._alpha); this._red = color[0]; this._green = color[1]; this._blue = color[2]; } else {throw Error('Assertion! Color(): Illegal color hash.');} break; case 3: case 4: this._red = arg1; this._green = arg2; this._blue = arg3; this._alpha = arg4 !== void 0 ? arg4 : 1; break; default: throw Error('Assertion! Color(): Illegal arguments.length (It\'s ' + arguments.length + ')'); } } /** * @param color1 Color * @param color2 Color * @return Color */ Color.add = function (color1, color2) { var result = new Color(color1._red, color1._green, color1._blue, color1._alpha); return result.add(color2); }; /** * @param color1 Color * @param color2 Color * @return Color */ Color.sub = function (color1, color2) { var result = new Color(color1._red, color1._green, color1._blue, color1._alpha); return result.sub(color2); }; /** * @param color Color * @param denominator Number * @return Color */ Color.div = function (color, denominator) { var result = new Color(color._red, color._green, color._blue, color._alpha); return result.div(denominator); } /** * @param colorStart Color * @param colorEnd Color * @param sequenceNumber Number NaturalNumber. result.length * @return Color[] */ Color.generateSequence = function (colorStart, colorEnd, sequenceNumber) { var i, result = new Array(sequenceNumber), diff = Color.sub(colorStart, colorEnd).div(sequenceNumber - 1); result[0] = colorStart; for (i = 1; i < sequenceNumber - 1; i += 1) { result[i] = Color.add(result[i - 1], diff); } result[sequenceNumber - 1] = colorEnd; return result; }; Color.prototype = { /** * Setter. For setter, don't touch raw property. Must use this. * @param colorHash Hash * @return Color this */ set: function (colorHash) { var hsla, rgba; ['red r', 'grren g', 'blue b', 'hue h', 'saturation s', 'lightness l', 'alpha a'].forEach(function (elm) { var names = elm.split(' '); if (!colorHash[name[0]] === void 0) { colorHash[name[0]] = colorName[name[1]]; } }); if (colorHash.red !== void 0 || colorHash.green !== void 0 || colorHash.blue !== void 0) { rgba = [colorHash.red !== void 0 ? colorHash.red : this._red, colorHash.green !== void 0 ? colorHash.green : this._green, colorHash.blue !== void 0 ? colorHash.blue : this._blue, colorHash.alpha]; hsla = convertRgbaToHsla(rgba[0], rgba[1], rgba[2], rgba[3]); this._hue = hsla[0]; this._saturation = hsla[1]; this._lightness = hlsa[2]; } else if (colorHash.hue !== void 0 || colorHash.saturation !== void 0 || colorHash.blue !== void 0) { hsla = [colorHash.hue !== void 0 ? colorHash.hue : this._hue, colorHash.saturation !== void 0 ? colorHash.saturation : this._saturation, colorHash.lightness !== void 0 ? colorHash.lightness : this._lightness, colorHash.alpha]; rgba = convertHslaToRgba(hsla[0], hsla[1], hsla[2], hsla[3]); this._red = rgba[0]; this._green = rgba[1]; this._blue = rgba[2]; } if (colorHash.alpha !== void 0) { this._alpha = colorHash.alpha; } return this; }, /** * @return Array [red Number, green Number, blue Number, alpha Number] */ rgba: function () {return [this._red, this._green, this._blue, this._alpha];}, /** * @return Array [hue Number, saturation Number, lightness Number, alpha Number] */ hsla: function () {return [this._hue, this._saturation, this._lightness, this._alpha];}, /** * @return Array [red Number, green Number, blue Number] */ rgb: function () {return [this._red, this._green, this._blue];}, /** * @return Array [hue Number, saturation Number, lightness Number] */ hsl: function () {return [this._hue, this._saturation, this._lightness];}, /** * @param color Color * @return Color this */ add: function (color) { var hash = { red: this._red + color._red, green: this._green + color._green, blue: this._blue + color._blue, alpha: 1 - (1 - this._alpha) * (1 - color._alpha) }; if (hash.red > 255) {hash.red = 255;} if (hash.green > 255) {hash.green = 255;} if (hash.blue > 255) {hash.blue = 255;} this.set(hash); return this; }, /** * @param color Color * @return Color this */ sub: function (color) { var hash = { red: this._red - color._red, green: this._green - color._green, blue: this._blue - color._blue, alpha: color._alpha === 1 ? 0 : (this._alpha - color._alpha) / (1 - color._alpha) }; if (hash.red < 0) {hash.red = 0;} if (hash.green < 0) {hash.green = 0;} if (hash.blue < 0) {hash.blue = 0;} this.set(hash); return this; }, /** * @param denominator Number * @return Color this */ div: function (denominator) { if (!denominator) { throw Error('Assertion! Color.prototype.div(): The denominator must not be zero.'); } this.set({ red: this._red / denominator, green: this._green / denominator, blue: this._blue / denominator, alpha: this._alpha }); return this; } }; (function () { var Color_prototype = Color.prototype; defineGetterAndSetter(Color_prototype, 'red', function () {return this._red;}, function (val) { this.set({red: val}); return this; }); defineGetterAndSetter(Color_prototype, 'green', function () {return this._green;}, function (val) { this.set({green: val}); return this; }); defineGetterAndSetter(Color_prototype, 'blue', function () {return this._blue;}, function (val) { this.set({blue: val}); return this; }); defineGetterAndSetter(Color_prototype, 'hue', function () {return this._hue;}, function (val) { this.set({hue: val}); return this; }); defineGetterAndSetter(Color_prototype, 'saturation', function () {return this._saturation;}, function (val) { this.set({saturation: val}); return this; }); defineGetterAndSetter(Color_prototype, 'lightness', function () {return this._lightness;}, function (val) { this.set({lightness: val}); return this; }); defineGetterAndSetter(Color_prototype, 'alpha', function () {return this._alpha;}, function (val) { this._alpha = val; return this; }); mixin(Color_prototype, { r: Color_prototype.red, g: Color_prototype.green, b: Color_prototype.blue, h: Color_prototype.hue, s: Color_prototype.saturation, l: Color_prototype.lightness, a: Color_prototype.alpha, }); }()); return Color; }());