| 1 | (function (Raphael) { |
| 2 | Raphael.colorwheel = function (x, y, size, initcolor, element) { |
| 3 | return new ColorWheel(x, y, size, initcolor, element); |
| 4 | }; |
| 5 | var pi = Math.PI, |
| 6 | doc = document, |
| 7 | win = window, |
| 8 | ColorWheel = function (x, y, size, initcolor, element) { |
| 9 | size = size || 200; |
| 10 | var w3 = 3 * size / 200, |
| 11 | w1 = size / 200, |
| 12 | fi = 1.6180339887, |
| 13 | segments = pi * size / 5, |
| 14 | size20 = size / 20, |
| 15 | size2 = size / 2, |
| 16 | padding = 2 * size / 200, |
| 17 | t = this; |
| 18 | |
| 19 | var H = 1, S = 1, B = 1, s = size - (size20 * 4); |
| 20 | var r = element ? Raphael(element, size, size) : Raphael(x, y, size, size), |
| 21 | xy = s / 6 + size20 * 2 + padding, |
| 22 | wh = s * 2 / 3 - padding * 2; |
| 23 | w1 < 1 && (w1 = 1); |
| 24 | w3 < 1 && (w3 = 1); |
| 25 | |
| 26 | |
| 27 | // ring drawing |
| 28 | var a = pi / 2 - pi * 2 / segments * 1.3, |
| 29 | R = size2 - padding, |
| 30 | R2 = size2 - padding - size20 * 2, |
| 31 | path = ["M", size2, padding, "A", R, R, 0, 0, 1, R * Math.cos(a) + R + padding, R - R * Math.sin(a) + padding, "L", R2 * Math.cos(a) + R + padding, R - R2 * Math.sin(a) + padding, "A", R2, R2, 0, 0, 0, size2, padding + size20 * 2, "z"].join(); |
| 32 | for (var i = 0; i < segments; i++) { |
| 33 | r.path(path).attr({ |
| 34 | stroke: "none", |
| 35 | fill: "hsb(" + i * (255 / segments) / 255 + ", 1, 0.78)", |
| 36 | transform: "r" + [(360 / segments) * i, size2, size2] |
| 37 | }); |
| 38 | } |
| 39 | r.path(["M", size2, padding, "A", R, R, 0, 1, 1, size2 - 1, padding, "l1,0", "M", size2, padding + size20 * 2, "A", R2, R2, 0, 1, 1, size2 - 1, padding + size20 * 2, "l1,0"]).attr({ |
| 40 | "stroke-width": w3, |
| 41 | stroke: "#fff" |
| 42 | }); |
| 43 | t.cursorhsb = r.set(); |
| 44 | var h = size20 * 2 + 2; |
| 45 | t.cursorhsb.push(r.rect(size2 - h / fi / 2, padding - 1, h / fi, h, 3 * size / 200).attr({ |
| 46 | stroke: "#000", |
| 47 | opacity: .5, |
| 48 | "stroke-width": w3 |
| 49 | })); |
| 50 | t.cursorhsb.push(t.cursorhsb[0].clone().attr({ |
| 51 | stroke: "#fff", |
| 52 | opacity: 1, |
| 53 | "stroke-width": w1 |
| 54 | })); |
| 55 | t.ring = r.path(["M", size2, padding, "A", R, R, 0, 1, 1, size2 - 1, padding, "l1,0M", size2, padding + size20 * 2, "A", R2, R2, 0, 1, 1, size2 - 1, padding + size20 * 2, "l1,0"]).attr({ |
| 56 | fill: "#000", |
| 57 | opacity: 0, |
| 58 | stroke: "none" |
| 59 | }); |
| 60 | |
| 61 | // rect drawing |
| 62 | t.main = r.rect(xy, xy, wh, wh).attr({ |
| 63 | stroke: "none", |
| 64 | fill: "#f00", |
| 65 | opacity: 1 |
| 66 | }); |
| 67 | t.main.clone().attr({ |
| 68 | stroke: "none", |
| 69 | fill: "0-#fff-#fff", |
| 70 | opacity: 0 |
| 71 | }); |
| 72 | t.square = r.rect(xy - 1, xy - 1, wh + 2, wh + 2).attr({ |
| 73 | r: 2, |
| 74 | stroke: "#fff", |
| 75 | "stroke-width": w3, |
| 76 | fill: "90-#000-#000", |
| 77 | opacity: 0, |
| 78 | cursor: "crosshair" |
| 79 | }); |
| 80 | t.cursor = r.set(); |
| 81 | t.cursor.push(r.circle(size2, size2, size20 / 2).attr({ |
| 82 | stroke: "#000", |
| 83 | opacity: .5, |
| 84 | "stroke-width": w3 |
| 85 | })); |
| 86 | t.cursor.push(t.cursor[0].clone().attr({ |
| 87 | stroke: "#fff", |
| 88 | opacity: 1, |
| 89 | "stroke-width": w1 |
| 90 | })); |
| 91 | t.H = t.S = t.B = 1; |
| 92 | t.raphael = r; |
| 93 | t.size2 = size2; |
| 94 | t.wh = wh; |
| 95 | t.x = x; |
| 96 | t.xy = xy; |
| 97 | t.y = y; |
| 98 | |
| 99 | // events |
| 100 | t.ring.drag(function (dx, dy, x, y) { |
| 101 | t.docOnMove(dx, dy, x, y); |
| 102 | }, function (x, y) { |
| 103 | t.hsbOnTheMove = true; |
| 104 | t.setH(x - t.x - t.size2, y - t.y - t.size2); |
| 105 | }, function () { |
| 106 | t.hsbOnTheMove = false; |
| 107 | }); |
| 108 | t.square.drag(function (dx, dy, x, y) { |
| 109 | t.docOnMove(dx, dy, x, y); |
| 110 | }, function (x, y) { |
| 111 | t.clrOnTheMove = true; |
| 112 | t.setSB(x - t.x, y - t.y); |
| 113 | }, function () { |
| 114 | t.clrOnTheMove = false; |
| 115 | }); |
| 116 | |
| 117 | t.color(initcolor || "#f00"); |
| 118 | this.onchanged && this.onchanged(this.color()); |
| 119 | }, |
| 120 | proto = ColorWheel.prototype; |
| 121 | proto.setH = function (x, y) { |
| 122 | var d = Raphael.angle(x, y, 0, 0), |
| 123 | rd = Raphael.rad(d); |
| 124 | this.cursorhsb.attr({transform: "r" + [d + 90, this.size2, this.size2]}); |
| 125 | this.H = (d + 90) / 360; |
| 126 | this.main.attr({fill: "hsb(" + this.H + ",1,1)"}); |
| 127 | this.onchange && this.onchange(this.color()); |
| 128 | }; |
| 129 | proto.setSB = function (x, y) { |
| 130 | var me = this; |
| 131 | x < me.size2 - me.wh / 2 && (x = me.size2 - me.wh / 2); |
| 132 | x > me.size2 + me.wh / 2 && (x = me.size2 + me.wh / 2); |
| 133 | y < me.size2 - me.wh / 2 && (y = me.size2 - me.wh / 2); |
| 134 | y > me.size2 + me.wh / 2 && (y = me.size2 + me.wh / 2); |
| 135 | me.cursor.attr({cx: x, cy: y}); |
| 136 | me.B = 1 - (y - me.xy) / me.wh; |
| 137 | me.S = (x - me.xy) / me.wh; |
| 138 | me.onchange && me.onchange(me.color()); |
| 139 | }; |
| 140 | proto.docOnMove = function (dx, dy, x, y) { |
| 141 | if (this.hsbOnTheMove) { |
| 142 | this.setH(x - this.x - this.size2, y - this.y - this.size2); |
| 143 | } |
| 144 | if (this.clrOnTheMove) { |
| 145 | this.setSB(x - this.x, y - this.y); |
| 146 | } |
| 147 | }; |
| 148 | proto.remove = function () { |
| 149 | this.raphael.remove(); |
| 150 | this.color = function () { |
| 151 | return false; |
| 152 | }; |
| 153 | }; |
| 154 | proto.color = function (color) { |
| 155 | if (color) { |
| 156 | color = Raphael.color(color); |
| 157 | var d = color.h * 360; |
| 158 | this.H = color.h; |
| 159 | this.S = color.s; |
| 160 | this.B = color.v; |
| 161 | this.cursorhsb.attr({transform: "r" + [d, this.size2, this.size2]}); |
| 162 | this.main.attr({fill: "hsb(" + this.H + ",1,1)"}); |
| 163 | var x = this.S * this.wh + this.xy, |
| 164 | y = (1 - this.B) * this.wh + this.xy; |
| 165 | this.cursor.attr({cx: x, cy: y}); |
| 166 | return this; |
| 167 | } else { |
| 168 | return Raphael.hsb2rgb(this.H, this.S, this.B).hex; |
| 169 | } |
| 170 | }; |
| 171 | })(window.Raphael); |