├── README.md
├── img
└── logo.png
├── LICENSE
├── index.html
├── js
├── index.js
└── colorwheel.js
└── css
└── style.css
/README.md:
--------------------------------------------------------------------------------
1 | # LED RGB Guru
2 | RGB LED controller powered by AgnosThings API
3 |
--------------------------------------------------------------------------------
/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rivafarabi/LED-RGB-Guru/master/img/logo.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Riva Farabi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | RGB LED Guru by Riva Farabi
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | RGB LED Guru
24 |
25 |
26 | GUID
27 | SHARE
28 |
29 |
30 |
31 |
32 |
#hex
33 |
34 |
35 |
36 |
37 | by Riva Farabi 2016
38 | Color wheel by John Weir
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/js/index.js:
--------------------------------------------------------------------------------
1 | var profiles = {};
2 | var colors;
3 | var r;
4 | var g;
5 | var b;
6 | var yiq;
7 | var status = $(".status");
8 |
9 | $(document).ready(function () {
10 | loadColorWheel();
11 | })
12 |
13 | function loadColorWheel() {
14 | var cw = Raphael.colorwheel($(".colorwheel")[0], 300, 250)
15 | .color("#006eff")
16 | .ondrag(startDrag, stopDrag);
17 |
18 | cw.input($("body")[0]);
19 |
20 | function startDrag() {
21 | $(".status").text("").fadeIn();
22 | }
23 |
24 | function stopDrag() {
25 | console.log(r, g, b)
26 | sendAPI(r, g, b);
27 | }
28 |
29 | cw.onchange(function (color) {
30 | r = parseInt(color.r);
31 | g = parseInt(color.g);
32 | b = parseInt(color.b);
33 | yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
34 | $(".textcontrast").css("color", (yiq >= 128) ? 'black' : 'white');
35 | $("button").css("border-color", (yiq >= 128) ? 'black' : 'white');
36 | $(".svg-icon").css("fill", (yiq >= 128) ? 'black' : 'white');
37 | $(".hexcolor").text(color.hex);
38 | })
39 | }
40 |
41 | function sendAPI(r, g, b) {
42 | var xmlhttp = new XMLHttpRequest();
43 | xmlhttp.open("GET", "http://agnosthings.com/d0733d1a-08b0-11e6-8001-005056805279/feed?push=red=" + r + ",blue=" + b + ",green=" + g + ",active=" + 1);
44 | xmlhttp.onreadystatechange = function () {
45 | if (xmlhttp.status == 200) {
46 | var data = JSON.parse(xmlhttp.responseText);
47 | console.log(data.value);
48 | $(".status").text("color updated!").fadeOut(2000);
49 | } else {
50 | $(".status").text("error! check your internet connection.").fadeOut(2000);
51 | }
52 | }
53 | xmlhttp.send();
54 | }
55 |
56 | function showGuid() {
57 | alert("AgnosThings GUID : \n0733d1a-08b0-11e6-8001-005056805279");
58 | }
59 |
60 | function shareFacebook(){
61 | window.open("https://www.facebook.com/sharer/sharer.php?u=rgbledguru.droppages.com");
62 | }
--------------------------------------------------------------------------------
/css/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: 'Lato', sans-serif;
3 | margin: 0;
4 | -webkit-user-select: none;
5 | -moz-user-select: none;
6 | -ms-user-select: none;
7 | }
8 |
9 | button {
10 | height: 50px;
11 | padding: 8px;
12 | border: 1px solid white;
13 | border-radius: 6px;
14 | background-color: transparent;
15 | margin-right: 6px;
16 | margin-left: 6px;
17 | color: white;
18 | font-size: 16px;
19 | cursor: pointer;
20 | font-weight: 300;
21 | }
22 | button:hover{
23 | background-color: rgba(255,255,255,0.3);
24 | }
25 |
26 | header,
27 | footer,
28 | .hexcolor {
29 | color: white;
30 | }
31 |
32 | header {
33 | height: 60px;
34 | padding-left: 20px;
35 | padding-right: 20px;
36 | padding-top: 20px;
37 | }
38 |
39 | header .title {
40 | float: left;
41 | font-size: 32px;
42 | font-weight: 900;
43 | }
44 |
45 | header .title > span {
46 | font-weight: 300;
47 | }
48 |
49 | header .nav {
50 | position: relative;
51 | float: right;
52 | text-align: right;
53 | }
54 |
55 | i{
56 | vertical-align: middle;
57 | }
58 |
59 | footer {
60 | position: absolute;
61 | bottom: 0px;
62 | padding-top: 16px;
63 | padding-bottom: 16px;
64 | width: 100%;
65 | text-align: center;
66 | }
67 |
68 | .color-picker {
69 | position: absolute;
70 | margin: auto;
71 | margin-top: 40px;
72 | left: 0;
73 | right: 0;
74 | height: 300px;
75 | width: 300px;
76 | border-radius: 150px;
77 | background-color: white;
78 | border: 5px solid white;
79 | }
80 |
81 | .hexcolor {
82 | margin-top: 20px;
83 | color: white;
84 | font-size: 24pt;
85 | text-align: center;
86 | font-weight: 300;
87 | }
88 |
89 | .status{
90 | color: white;
91 | font-size: 24pt;
92 | font-weight: 300;
93 | text-align: center;
94 | }
95 |
96 | .sharebutton{
97 | float: left;
98 | padding: 7px;
99 | border: 1px solid white;
100 | border-radius: 6px;
101 | background-color: transparent;
102 | text-decoration: none;
103 | color: white;
104 | font-size: 18px;
105 | cursor: pointer;
106 | }
107 |
108 |
--------------------------------------------------------------------------------
/js/colorwheel.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Colorwheel
3 | * Copyright (c) 2010 John Weir (http://famedriver.com)
4 | * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
5 | *
6 | * requires jQuery & Raphael
7 | * http://jquery.com http://raphaeljs.com
8 | *
9 | * see http://jweir.github.com/colorwheel for Usage
10 | *
11 | */
12 |
13 | Raphael.colorwheel = function(target, color_wheel_size, no_segments){
14 | var canvas,
15 | current_color,
16 | current_color_hsb,
17 | size,
18 | segments = no_segments || 60,
19 | bs_square = {},
20 | hue_ring = {},
21 | tri_size,
22 | cursor = {},
23 | drag_target,
24 | input_target,
25 | center,
26 | parent,
27 | change_callback,
28 | drag_callbacks = [function(){}, function(){}],
29 | offset,
30 | padding = 2,
31 | sdim; // holds the dimensions for the saturation square
32 |
33 | function point(x, y){ return {x:x, y:y};}
34 | function radians(a){ return a * (Math.PI/180);}
35 |
36 | function angle(x,y){
37 | var q = x > 0 ? 0 : 180;
38 | return q+Math.atan((0 - y)/(0 - x))*180/(Math.PI);
39 | }
40 |
41 | function create(target, color_wheel_size){
42 | size = color_wheel_size;
43 | tri_size = size/20;
44 | center = size/2;
45 | parent = $(target);
46 | canvas = Raphael(parent[0],size, size);
47 | // canvas.safari();
48 |
49 | create_bs_square();
50 | create_hue_ring();
51 | hue_ring.cursor = cursor_create(tri_size);
52 | bs_square.cursor = cursor_create(tri_size*0.5);
53 | events_setup();
54 | parent.css({height:size+"px", width:size+"px"});
55 | disable_select(parent);
56 | return public_methods();
57 | }
58 |
59 | function disable_select(target){
60 | $(target).css({"unselectable": "on","-moz-user-select": "none","-webkit-user-select": "none"});
61 | }
62 |
63 | function public_methods(){
64 | return {
65 | input: input,
66 | onchange: onchange,
67 | ondrag : ondrag,
68 | color : public_set_color,
69 | color_hsb : public_set_color_hsb
70 | };
71 | }
72 |
73 | // Sets a textfield for user input of hex color values
74 | // TODO don't clear the change callback
75 | // TODO allow a null target to unbind the input
76 | function input(target){
77 | change_callback = null;
78 | input_target = target;
79 | $(target).keyup(function(){
80 | if(this.value.match(/^#([0-9A-F]){3}$|^#([0-9A-F]){6}$/img)){
81 | set_color(this.value);
82 | update_color(true);
83 | run_onchange_event();
84 | }
85 | });
86 | set_color(target.value);
87 | update_color(true);
88 |
89 | return public_methods();
90 | }
91 |
92 | function onchange(callback){
93 | change_callback = callback;
94 | update_color(false);
95 | return public_methods();
96 | }
97 |
98 | function ondrag(start_callback, end_callback){
99 | drag_callbacks = [start_callback || function(){}, end_callback || function(){}];
100 | return public_methods();
101 | }
102 |
103 | function drag(e){
104 | var x, y, page;
105 |
106 | e.preventDefault(); // prevents scrolling on touch
107 |
108 | page = e.originalEvent.touches ? e.originalEvent.touches[0] : e;
109 |
110 | x = page.pageX - (parent.offset().left + center);
111 | y = page.pageY - (parent.offset().top + center);
112 |
113 | if(drag_target == hue_ring){
114 | set_hue_cursor(x,y);
115 | update_color();
116 | run_onchange_event();
117 | return true;
118 | }
119 | if(drag_target == bs_square){
120 | set_bs_cursor(x,y);
121 | update_color();
122 | run_onchange_event();
123 | return true;
124 | }
125 | }
126 |
127 | function start_drag(event, target){
128 | event.preventDefault(); // prevents scrolling on touch
129 |
130 | $(document).on('mouseup touchend',stop_drag);
131 | $(document).on('mousemove touchmove',drag);
132 | drag_target = target;
133 | drag(event);
134 | drag_callbacks[0](current_color);
135 | }
136 |
137 | function stop_drag(event){
138 | event.preventDefault(); // prevents scrolling on touch
139 |
140 | $(document).off("mouseup touchend",stop_drag);
141 | $(document).off("mousemove touchmove",drag);
142 | drag_callbacks[1](current_color);
143 | run_onchange_event();
144 | }
145 |
146 | function events_setup(){
147 | $([hue_ring.event.node,hue_ring.cursor[0].node]).on("mousedown touchstart",
148 | function(e){start_drag(e,hue_ring);});
149 | $([bs_square.b.node, bs_square.cursor[0].node]).on("mousedown touchstart",
150 | function(e){start_drag(e,bs_square);});
151 | }
152 |
153 | function cursor_create(size){
154 | var set = canvas.set().push(
155 | canvas.circle(0, 0, size).attr({"stroke-width":4, stroke:"#333"}),
156 | canvas.circle(0, 0, size+2).attr({"stroke-width":1, stroke:"#FFF", opacity:0.5})
157 | );
158 |
159 | set[0].node.style.cursor = "crosshair";
160 |
161 | return set;
162 | }
163 |
164 | function set_bs_cursor(x,y){
165 | x = x+center;
166 | y = y+center;
167 | if(x < sdim.x){x = sdim.x}
168 | if(x > sdim.x+sdim.l){x = sdim.x+sdim.l}
169 | if(y < sdim.y){y = sdim.y}
170 | if(y > sdim.y+sdim.l){y = sdim.y + sdim.l}
171 |
172 | bs_square.cursor.attr({cx:x, cy:y}).transform("t0,0");
173 | }
174 |
175 |
176 | function set_hue(color){
177 | var hex = Raphael.getRGB(color).hex;
178 | bs_square.h.attr("fill", hex);
179 | }
180 |
181 | function hue(){
182 | return Raphael.rgb2hsb(bs_square.h.attr("fill")).h;
183 | }
184 |
185 | function public_set_color(value){
186 | var ret = set_color(value, false);
187 | update_color(false);
188 | return ret;
189 | }
190 |
191 | function public_set_color_hsb(hsb){
192 | var ret = set_color(hsb, true);
193 | update_color(false);
194 | return ret;
195 | }
196 |
197 | function set_color(value, is_hsb){
198 | if(value === undefined){
199 | if(is_hsb){
200 | return current_color_hsb;
201 | } else {
202 | return current_color;
203 | }
204 | }
205 |
206 | var hsb, hex;
207 | if(is_hsb){
208 | hsb = value;
209 | // Allow v (value) instead of b (brightness), as v is sometimes
210 | // used by Raphael.
211 | if(hsb.b === undefined){ hsb.b = hsb.v; }
212 | var rgb = canvas.raphael.hsb2rgb(hsb.h, hsb.s, hsb.b);
213 | hex = rgb.hex;
214 | } else {
215 | hex = value;
216 | hsb = canvas.raphael.rgb2hsb(hex);
217 | }
218 | var temp = canvas.rect(1,1,1,1).attr({fill:hex});
219 |
220 | set_bs_cursor(
221 | (0-sdim.l/2) + (sdim.l*hsb.s),
222 | sdim.l/2 - (sdim.l*hsb.b));
223 | set_hue_cursor((360*(hsb.h))-90);
224 | temp.remove();
225 | return public_methods();
226 | }
227 |
228 | // Could optimize this method
229 | function update_color(dont_replace_input_value){
230 | var x = bs_square.cursor.items[0].attr("cx"),
231 | y = bs_square.cursor.items[0].attr("cy"),
232 | hsb = {
233 | b: 1-(y-sdim.y)/sdim.l,
234 | s: (x-sdim.x)/sdim.l,
235 | h: hue()
236 | };
237 |
238 |
239 | current_color_hsb = hsb;
240 | current_color = Raphael.hsb2rgb(hsb.h, hsb.s,hsb.b);
241 |
242 | if(input_target){
243 | var c = current_color.hex;
244 | if(dont_replace_input_value !== true) { input_target.value = c;}
245 | if(hsb.b < 0.5){
246 | $(input_target).css("color", "#FFF");
247 | } else {
248 | $(input_target).css("color", "#000");
249 | }
250 | input_target.style.background = c;
251 | }
252 |
253 | }
254 |
255 | // accepts either x,y or d (degrees)
256 | function set_hue_cursor(mixed_args){
257 | var d;
258 | if(arguments.length == 2){
259 | d = angle(arguments[0],arguments[1]);
260 | } else {
261 | d = arguments[0];
262 | }
263 |
264 | var x = Math.cos(radians(d)) * (center-tri_size-padding);
265 | var y = Math.sin(radians(d)) * (center-tri_size-padding);
266 | hue_ring.cursor.attr({cx:x+center, cy:y+center}).transform("t0,0");
267 | set_hue("hsb("+(d+90)/360+",1,1)");
268 | }
269 |
270 | function bs_square_dim(){
271 | if(sdim){ return sdim;}
272 | var s = size - (tri_size * 4);
273 | sdim = {
274 | x:(s/6)+tri_size*2+padding,
275 | y:(s/6)+tri_size*2+padding,
276 | l:(s * 2/3)-padding*2
277 | };
278 | return sdim;
279 | }
280 |
281 | function create_bs_square(){
282 | bs_square_dim();
283 | box = [sdim.x, sdim.y, sdim.l, sdim.l];
284 |
285 | bs_square.h = canvas.rect.apply(canvas, box).attr({
286 | stroke:"#EEE", gradient: "0-#FFF-#000", opacity:1});
287 | bs_square.s = canvas.rect.apply(canvas, box).attr({
288 | stroke:null, gradient: "0-#FFF-#FFF", opacity:0});
289 | bs_square.b = canvas.rect.apply(canvas, box).attr({
290 | stroke:null, gradient: "90-#000-#FFF", opacity:0});
291 | bs_square.b.node.style.cursor = "crosshair";
292 | }
293 |
294 | function hue_segement_shape(){
295 | var path = "M -@W 0 L @W 0 L @W @H L -@W @H z";
296 | return path.replace(/@H/img, tri_size*2).replace(/@W/img,tri_size);
297 | }
298 |
299 | function copy_segment(r, d, k){
300 | var n = r.clone();
301 | var hue = d*(255/k);
302 |
303 | var s = size/2,
304 | t = tri_size,
305 | p = padding;
306 |
307 | n.transform("t"+s+","+(s-t)+"r"+(360/k)*d+"t0,-"+(s-t-p)+"");
308 |
309 | n.attr({"stroke-width":0, fill:"hsb("+d*(1/k)+", 1, 0.85)"});
310 | hue_ring.hues.push(n);
311 | }
312 |
313 | function create_hue_ring(){
314 | var s = hue_segement_shape(),
315 | tri = canvas.path(s).attr({stroke:"rgba(0,0,0,0)"}).transform("t"+(size/2)+","+padding),
316 | k = segments; // # of segments to use to generate the hues
317 |
318 | hue_ring.hues = canvas.set();
319 |
320 | for(n=0; n