index.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php
  2. // check for a POST request and use curl to send data to the esp8266
  3. if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  4. $code = 400;
  5. $msg = strval($code) . " Bad Request";
  6. //error_log("post: " . print_r($_POST, true));
  7. if(isset($_POST["color"])) {
  8. // adject code and message when valid post is provided
  9. $code = 200;
  10. $msg = strval($code) . " OK";
  11. // start with off as default
  12. $color = "000000";
  13. // [!] protect curl from injection
  14. for($i = 6; $i--; ) $color[$i] = (isset($_POST["color"][$i]) && ctype_xdigit($_POST["color"][$i]))
  15. ? $_POST["color"][$i]
  16. : '0';
  17. $ch = curl_init();
  18. curl_setopt($ch, CURLOPT_URL,"http://rain-gutter-rgb.lan.rome7.com/rgb");
  19. curl_setopt($ch, CURLOPT_POST, 1);
  20. curl_setopt($ch, CURLOPT_POSTFIELDS, "color={$color}");
  21. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  22. $out = curl_exec($ch);
  23. curl_close($ch);
  24. }
  25. // set headers
  26. header("HTTP/1.0 {$msg}");
  27. $GLOBALS["http_response_code"] = $code;
  28. //http_response_code($code);
  29. exit("{$out}");
  30. }
  31. echo "<html>";
  32. echo "<body>";
  33. // either use mixbox non-commercial use under the CC BY-NC 4.0 license
  34. echo "<script src='mixbox.js'></script>";
  35. // or the spectral.js MIT license
  36. echo "<script src='spectral.js'></script>";
  37. echo "
  38. <script>
  39. // example mixing two colors
  40. var rgb1 = 'rgb(0, 33, 133)'; // blue
  41. var rgb2 = 'rgb(252, 211, 0)'; // yellow
  42. var t = 0.5; // mixing ratio
  43. var mixed = mixbox.lerp(rgb1, rgb2, t);
  44. console.log(mixed);
  45. // example mixing multiple colors
  46. var z1 = mixbox.rgbToLatent(rgb1);
  47. var z2 = mixbox.rgbToLatent(rgb2);
  48. var z3 = mixbox.rgbToLatent(mixed);
  49. var zMix = new Array(mixbox.LATENT_SIZE);
  50. for (var i = 0; i < zMix.length; i++) { // mix:
  51. zMix[i] = (0.3*z1[i] + // 30% of rgb1
  52. 0.6*z2[i] + // 60% of rgb2
  53. 0.1*z3[i]); // 10% of mixed
  54. }
  55. var rgbMix = mixbox.latentToRgb(zMix);
  56. console.log(rgbMix);
  57. // using spectral.js to mix two colors (does not seem to be working..., returns [0,0,0])
  58. var color = spectral.mix('[0, 33, 133]', '[252, 211, 0]', 0.5, spectral.RGB);
  59. console.log(color);
  60. </script>
  61. ";
  62. // render a color selection wheel
  63. echo "
  64. <script>
  65. var canvas = document.createElement('canvas');
  66. // google chrome performance flag
  67. //var context = canvas.getContext('2d');
  68. var context = canvas.getContext('2d', { willReadFrequently: true });
  69. var w = 200; var h = 200;
  70. canvas.width = w;
  71. canvas.height = h;
  72. for(var i = 0; i < 360; i += 0.1) {
  73. var rad = i * (2 * Math.PI) / 360;
  74. var x1 = w/2 + w/2 * Math.cos(rad);
  75. var y1 = h/2 + h/2 * Math.sin(rad);
  76. var gradient = context.createLinearGradient(w/2, h/2, x1, y1);
  77. gradient.addColorStop(0.0, 'white');
  78. gradient.addColorStop(1.0, 'hsla('+i+', 100%, 50%, 1.0)');
  79. context.strokeStyle = gradient;
  80. context.beginPath();
  81. context.moveTo(w/2, h/2);
  82. context.lineTo(x1, y1);
  83. context.stroke();
  84. }
  85. document.body.appendChild(canvas);
  86. </script>
  87. ";
  88. // simple color picker
  89. echo "
  90. <script>
  91. function tableData(c, head = false) {
  92. let td = document.createElement(head ?'th' :'td');
  93. if(typeof c === 'string' || c instanceof String) td.innerText = c;
  94. else td.appendChild(c);
  95. return td;
  96. }
  97. // create a table
  98. var table = document.createElement('table');
  99. var tableHead = document.createElement('thead');
  100. table.appendChild(tableHead);
  101. var tableHeadRow = document.createElement('tr');
  102. tableHead.appendChild(tableHeadRow);
  103. var tableBody = document.createElement('tbody');
  104. table.appendChild(tableBody);
  105. var tableBodyRow = document.createElement('tr');
  106. tableBody.appendChild(tableBodyRow);
  107. // add some headers
  108. tableHeadRow.appendChild(tableData('', true));
  109. tableHeadRow.appendChild(tableData('hover', true));
  110. tableHeadRow.appendChild(tableData('selected', true));
  111. // add table data
  112. tableBodyRow.appendChild(tableData(canvas));
  113. hovered = tableData(''); hovered.id = 'hovered-color';
  114. tableBodyRow.appendChild(hovered);
  115. selected = tableData(''); selected.id = 'selected-color';
  116. tableBodyRow.appendChild(selected);
  117. document.body.appendChild(table);
  118. // listen to events from canvas
  119. function pick(event, destination, cb = false) {
  120. const bounding = canvas.getBoundingClientRect();
  121. const x = event.clientX - bounding.left;
  122. const y = event.clientY - bounding.top;
  123. const pixel = context.getImageData(x, y, 1, 1);
  124. const data = pixel.data;
  125. //console.log(pixel, data);
  126. const rgb = 'rgb(' + data[0] + ', ' + data[1] + ', ' + data[2] + ')';
  127. let off = 0 === (data[0] | data[1] | data[2]);
  128. destination.style.background = off ?'rgb(211, 211, 211)' :rgb;
  129. destination.textContent = rgb;
  130. // handle optional callback
  131. if(false !== cb) cb(data[0], data[1], data[2]);
  132. return rgb;
  133. }
  134. canvas.addEventListener('mousemove', (event) => pick(event, hovered));
  135. canvas.addEventListener('click', (event) => pick(event, selected));
  136. </script>
  137. ";
  138. // add a callback to the click event to send rgb value to esp8266
  139. echo "
  140. <script>
  141. // using the newer fetch API, not sure if this is worse than AJAX
  142. async function post(url = '', color = '000000') {
  143. // to use _POST superblogal, send body as http multipart/form-data
  144. let fd = new FormData();
  145. fd.append('color', color);
  146. return await fetch(url, { method: 'POST', body: fd });
  147. }
  148. function sg(x) { return Math.round((x*x)/255); }
  149. function callback(red, green, blue) {
  150. console.log('logged', red, green, blue);
  151. post(
  152. /* url */ '',
  153. sg(red).toString(16).padStart(2,'0') +
  154. sg(green).toString(16).padStart(2,'0') +
  155. sg(blue).toString(16).padStart(2,'0')
  156. ).then((data) => { console.log(data, data.text()); });
  157. }
  158. canvas.removeEventListener('click', (event) => pick(event, selected));
  159. canvas.addEventListener('click', (event) => pick(event, selected, callback));
  160. </script>
  161. ";
  162. echo "</body>";
  163. echo "</html>";