Skip to content

Commit bea04e4

Browse files
committed
make example web app not depend on externally hosted assets, to support AP without internet
1 parent a349bac commit bea04e4

File tree

2 files changed

+126
-27
lines changed

2 files changed

+126
-27
lines changed

examples/server/static/index.html

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
5-
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-minicolors/2.3.4/jquery.minicolors.min.js"></script>
64
<script async src="led_color_picker_example.js"></script>
7-
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-minicolors/2.3.4/jquery.minicolors.css" />
8-
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" />
95
</head>
106
<body>
117
<h1>LED color picker demo!</h1>
12-
<input id="colorPicker" type=text/>
8+
<canvas id="colorPicker" height="300px" width="300px"></canvas>
139
</body>
1410
</html>
Lines changed: 125 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,126 @@
1-
console.log("initializing color picker")
2-
var colorPicker = $('input#colorPicker');
3-
colorPicker.minicolors({
4-
format: "rgb",
5-
changeDelay: 200,
6-
change: function (value, opacity) {
7-
rgbObject = colorPicker.minicolors("rgbObject");
8-
console.log(rgbObject);
9-
$.ajax({
10-
type: "POST",
11-
url: "/ajax/ledcolor",
12-
data: JSON.stringify(rgbObject),
13-
contentType: "application/json; charset=utf-8",
14-
dataType: "json",
15-
success: function(data){
16-
console.log("success!");
17-
},
18-
failure: function(errMsg) {
19-
console.log("error! " + errMsg);
20-
}
21-
});
1+
let canvas = document.getElementById('colorPicker');
2+
let ctx = canvas.getContext("2d");
3+
ctx.width = 300;
4+
ctx.height = 300;
5+
6+
function drawColorPicker() {
7+
/**
8+
* Color picker inspired by:
9+
* https://medium.com/@bantic/hand-coding-a-color-wheel-with-canvas-78256c9d7d43
10+
*/
11+
let radius = 150;
12+
let image = ctx.createImageData(2*radius, 2*radius);
13+
let data = image.data;
14+
15+
for (let x = -radius; x < radius; x++) {
16+
for (let y = -radius; y < radius; y++) {
17+
18+
let [r, phi] = xy2polar(x, y);
19+
20+
if (r > radius) {
21+
// skip all (x,y) coordinates that are outside of the circle
22+
continue;
23+
}
24+
25+
let deg = rad2deg(phi);
26+
27+
// Figure out the starting index of this pixel in the image data array.
28+
let rowLength = 2*radius;
29+
let adjustedX = x + radius; // convert x from [-50, 50] to [0, 100] (the coordinates of the image data array)
30+
let adjustedY = y + radius; // convert y from [-50, 50] to [0, 100] (the coordinates of the image data array)
31+
let pixelWidth = 4; // each pixel requires 4 slots in the data array
32+
let index = (adjustedX + (adjustedY * rowLength)) * pixelWidth;
33+
34+
let hue = deg;
35+
let saturation = r / radius;
36+
let value = 1.0;
37+
38+
let [red, green, blue] = hsv2rgb(hue, saturation, value);
39+
let alpha = 255;
40+
41+
data[index] = red;
42+
data[index+1] = green;
43+
data[index+2] = blue;
44+
data[index+3] = alpha;
45+
}
2246
}
23-
});
47+
48+
ctx.putImageData(image, 0, 0);
49+
}
50+
51+
function xy2polar(x, y) {
52+
let r = Math.sqrt(x*x + y*y);
53+
let phi = Math.atan2(y, x);
54+
return [r, phi];
55+
}
56+
57+
// rad in [-π, π] range
58+
// return degree in [0, 360] range
59+
function rad2deg(rad) {
60+
return ((rad + Math.PI) / (2 * Math.PI)) * 360;
61+
}
62+
63+
// hue in range [0, 360]
64+
// saturation, value in range [0,1]
65+
// return [r,g,b] each in range [0,255]
66+
// See: https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV
67+
function hsv2rgb(hue, saturation, value) {
68+
let chroma = value * saturation;
69+
let hue1 = hue / 60;
70+
let x = chroma * (1- Math.abs((hue1 % 2) - 1));
71+
let r1, g1, b1;
72+
if (hue1 >= 0 && hue1 <= 1) {
73+
([r1, g1, b1] = [chroma, x, 0]);
74+
} else if (hue1 >= 1 && hue1 <= 2) {
75+
([r1, g1, b1] = [x, chroma, 0]);
76+
} else if (hue1 >= 2 && hue1 <= 3) {
77+
([r1, g1, b1] = [0, chroma, x]);
78+
} else if (hue1 >= 3 && hue1 <= 4) {
79+
([r1, g1, b1] = [0, x, chroma]);
80+
} else if (hue1 >= 4 && hue1 <= 5) {
81+
([r1, g1, b1] = [x, 0, chroma]);
82+
} else if (hue1 >= 5 && hue1 <= 6) {
83+
([r1, g1, b1] = [chroma, 0, x]);
84+
}
85+
86+
let m = value - chroma;
87+
let [r,g,b] = [r1+m, g1+m, b1+m];
88+
89+
// Change r,g,b values from [0,1] to [0,255]
90+
return [255*r,255*g,255*b];
91+
}
92+
93+
function onColorPick(event) {
94+
coords = getCursorPosition(canvas, event)
95+
imageData = ctx.getImageData(coords[0],coords[1],1,1)
96+
rgbObject = {
97+
r: imageData.data[0],
98+
g: imageData.data[1],
99+
b: imageData.data[2]
100+
}
101+
console.log(`r: ${rgbObject.r} g: ${rgbObject.g} b: ${rgbObject.b}`);
102+
data = JSON.stringify(rgbObject);
103+
window.fetch("/ajax/ledcolor", {
104+
method: "POST",
105+
body: data,
106+
headers: {
107+
'Content-Type': 'application/json; charset=utf-8',
108+
},
109+
}).then(response => {
110+
console.log("sucess!: " + response)
111+
}, error => {
112+
console.log("error!: " + error)
113+
})
114+
}
115+
116+
function getCursorPosition(canvas, event) {
117+
const rect = canvas.getBoundingClientRect()
118+
const x = event.clientX - rect.left
119+
const y = event.clientY - rect.top
120+
console.log("x: " + x + " y: " + y)
121+
return [x,y]
122+
}
123+
124+
drawColorPicker();
125+
canvas.addEventListener('mousedown', onColorPick);
126+

0 commit comments

Comments
 (0)