|
@@ -0,0 +1,181 @@
|
|
|
|
+<?php
|
|
|
|
+// check for a POST request and use curl to send data to the esp8266
|
|
|
|
+if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
|
+ $code = 400;
|
|
|
|
+ $msg = strval($code) . " Bad Request";
|
|
|
|
+ //error_log("post: " . print_r($_POST, true));
|
|
|
|
+ if(isset($_POST["color"])) {
|
|
|
|
+ // adject code and message when valid post is provided
|
|
|
|
+ $code = 200;
|
|
|
|
+ $msg = strval($code) . " OK";
|
|
|
|
+ // start with off as default
|
|
|
|
+ $color = "000000";
|
|
|
|
+ // [!] protect curl from injection
|
|
|
|
+ for($i = 6; $i--; ) $color[$i] = (isset($_POST["color"][$i]) && ctype_xdigit($_POST["color"][$i]))
|
|
|
|
+ ? $_POST["color"][$i]
|
|
|
|
+ : '0';
|
|
|
|
+ $ch = curl_init();
|
|
|
|
+ curl_setopt($ch, CURLOPT_URL,"http://rain-gutter-rgb.lan.rome7.com/rgb");
|
|
|
|
+ curl_setopt($ch, CURLOPT_POST, 1);
|
|
|
|
+ curl_setopt($ch, CURLOPT_POSTFIELDS, "color={$color}");
|
|
|
|
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
+ $out = curl_exec($ch);
|
|
|
|
+ curl_close($ch);
|
|
|
|
+ }
|
|
|
|
+ // set headers
|
|
|
|
+ header("HTTP/1.0 {$msg}");
|
|
|
|
+ $GLOBALS["http_response_code"] = $code;
|
|
|
|
+ //http_response_code($code);
|
|
|
|
+ exit("{$out}");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+echo "<html>";
|
|
|
|
+echo "<body>";
|
|
|
|
+// either use mixbox non-commercial use under the CC BY-NC 4.0 license
|
|
|
|
+echo "<script src='mixbox.js'></script>";
|
|
|
|
+// or the spectral.js MIT license
|
|
|
|
+echo "<script src='spectral.js'></script>";
|
|
|
|
+echo "
|
|
|
|
+<script>
|
|
|
|
+// example mixing two colors
|
|
|
|
+var rgb1 = 'rgb(0, 33, 133)'; // blue
|
|
|
|
+var rgb2 = 'rgb(252, 211, 0)'; // yellow
|
|
|
|
+var t = 0.5; // mixing ratio
|
|
|
|
+var mixed = mixbox.lerp(rgb1, rgb2, t);
|
|
|
|
+console.log(mixed);
|
|
|
|
+
|
|
|
|
+// example mixing multiple colors
|
|
|
|
+var z1 = mixbox.rgbToLatent(rgb1);
|
|
|
|
+var z2 = mixbox.rgbToLatent(rgb2);
|
|
|
|
+var z3 = mixbox.rgbToLatent(mixed);
|
|
|
|
+var zMix = new Array(mixbox.LATENT_SIZE);
|
|
|
|
+for (var i = 0; i < zMix.length; i++) { // mix:
|
|
|
|
+ zMix[i] = (0.3*z1[i] + // 30% of rgb1
|
|
|
|
+ 0.6*z2[i] + // 60% of rgb2
|
|
|
|
+ 0.1*z3[i]); // 10% of mixed
|
|
|
|
+}
|
|
|
|
+var rgbMix = mixbox.latentToRgb(zMix);
|
|
|
|
+console.log(rgbMix);
|
|
|
|
+
|
|
|
|
+// using spectral.js to mix two colors (does not seem to be working..., returns [0,0,0])
|
|
|
|
+var color = spectral.mix('[0, 33, 133]', '[252, 211, 0]', 0.5, spectral.RGB);
|
|
|
|
+console.log(color);
|
|
|
|
+
|
|
|
|
+</script>
|
|
|
|
+";
|
|
|
|
+
|
|
|
|
+// render a color selection wheel
|
|
|
|
+echo "
|
|
|
|
+<script>
|
|
|
|
+var canvas = document.createElement('canvas');
|
|
|
|
+// google chrome performance flag
|
|
|
|
+//var context = canvas.getContext('2d');
|
|
|
|
+var context = canvas.getContext('2d', { willReadFrequently: true });
|
|
|
|
+var w = 200; var h = 200;
|
|
|
|
+canvas.width = w;
|
|
|
|
+canvas.height = h;
|
|
|
|
+
|
|
|
|
+for(var i = 0; i < 360; i += 0.1) {
|
|
|
|
+ var rad = i * (2 * Math.PI) / 360;
|
|
|
|
+ var x1 = w/2 + w/2 * Math.cos(rad);
|
|
|
|
+ var y1 = h/2 + h/2 * Math.sin(rad);
|
|
|
|
+ var gradient = context.createLinearGradient(w/2, h/2, x1, y1);
|
|
|
|
+ gradient.addColorStop(0.0, 'white');
|
|
|
|
+ gradient.addColorStop(1.0, 'hsla('+i+', 100%, 50%, 1.0)');
|
|
|
|
+ context.strokeStyle = gradient;
|
|
|
|
+ context.beginPath();
|
|
|
|
+ context.moveTo(w/2, h/2);
|
|
|
|
+ context.lineTo(x1, y1);
|
|
|
|
+ context.stroke();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+document.body.appendChild(canvas);
|
|
|
|
+
|
|
|
|
+</script>
|
|
|
|
+";
|
|
|
|
+
|
|
|
|
+// simple color picker
|
|
|
|
+echo "
|
|
|
|
+<script>
|
|
|
|
+function tableData(c, head = false) {
|
|
|
|
+ let td = document.createElement(head ?'th' :'td');
|
|
|
|
+ if(typeof c === 'string' || c instanceof String) td.innerText = c;
|
|
|
|
+ else td.appendChild(c);
|
|
|
|
+ return td;
|
|
|
|
+}
|
|
|
|
+// create a table
|
|
|
|
+var table = document.createElement('table');
|
|
|
|
+var tableHead = document.createElement('thead');
|
|
|
|
+table.appendChild(tableHead);
|
|
|
|
+var tableHeadRow = document.createElement('tr');
|
|
|
|
+tableHead.appendChild(tableHeadRow);
|
|
|
|
+var tableBody = document.createElement('tbody');
|
|
|
|
+table.appendChild(tableBody);
|
|
|
|
+var tableBodyRow = document.createElement('tr');
|
|
|
|
+tableBody.appendChild(tableBodyRow);
|
|
|
|
+// add some headers
|
|
|
|
+tableHeadRow.appendChild(tableData('', true));
|
|
|
|
+tableHeadRow.appendChild(tableData('hover', true));
|
|
|
|
+tableHeadRow.appendChild(tableData('selected', true));
|
|
|
|
+// add table data
|
|
|
|
+tableBodyRow.appendChild(tableData(canvas));
|
|
|
|
+hovered = tableData(''); hovered.id = 'hovered-color';
|
|
|
|
+tableBodyRow.appendChild(hovered);
|
|
|
|
+selected = tableData(''); selected.id = 'selected-color';
|
|
|
|
+tableBodyRow.appendChild(selected);
|
|
|
|
+
|
|
|
|
+document.body.appendChild(table);
|
|
|
|
+
|
|
|
|
+// listen to events from canvas
|
|
|
|
+function pick(event, destination, cb = false) {
|
|
|
|
+ const bounding = canvas.getBoundingClientRect();
|
|
|
|
+ const x = event.clientX - bounding.left;
|
|
|
|
+ const y = event.clientY - bounding.top;
|
|
|
|
+ const pixel = context.getImageData(x, y, 1, 1);
|
|
|
|
+ const data = pixel.data;
|
|
|
|
+ //console.log(pixel, data);
|
|
|
|
+
|
|
|
|
+ const rgb = 'rgb(' + data[0] + ', ' + data[1] + ', ' + data[2] + ')';
|
|
|
|
+ let off = 0 === (data[0] | data[1] | data[2]);
|
|
|
|
+ destination.style.background = off ?'rgb(211, 211, 211)' :rgb;
|
|
|
|
+ destination.textContent = rgb;
|
|
|
|
+
|
|
|
|
+ // handle optional callback
|
|
|
|
+ if(false !== cb) cb(data[0], data[1], data[2]);
|
|
|
|
+
|
|
|
|
+ return rgb;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+canvas.addEventListener('mousemove', (event) => pick(event, hovered));
|
|
|
|
+canvas.addEventListener('click', (event) => pick(event, selected));
|
|
|
|
+
|
|
|
|
+</script>
|
|
|
|
+";
|
|
|
|
+
|
|
|
|
+// add a callback to the click event to send rgb value to esp8266
|
|
|
|
+echo "
|
|
|
|
+<script>
|
|
|
|
+// using the newer fetch API, not sure if this is worse than AJAX
|
|
|
|
+async function post(url = '', color = '000000') {
|
|
|
|
+ // to use _POST superblogal, send body as http multipart/form-data
|
|
|
|
+ let fd = new FormData();
|
|
|
|
+ fd.append('color', color);
|
|
|
|
+ return await fetch(url, { method: 'POST', body: fd });
|
|
|
|
+}
|
|
|
|
+function callback(red, green, blue) {
|
|
|
|
+ console.log('logged', red, green, blue);
|
|
|
|
+ post(
|
|
|
|
+ /* url */ '',
|
|
|
|
+ red.toString(16).padStart(2,'0') +
|
|
|
|
+ green.toString(16).padStart(2,'0') +
|
|
|
|
+ blue.toString(16).padStart(2,'0')
|
|
|
|
+ ).then((data) => { console.log(data, data.text()); });
|
|
|
|
+}
|
|
|
|
+canvas.removeEventListener('click', (event) => pick(event, selected));
|
|
|
|
+canvas.addEventListener('click', (event) => pick(event, selected, callback));
|
|
|
|
+
|
|
|
|
+</script>
|
|
|
|
+";
|
|
|
|
+
|
|
|
|
+echo "</body>";
|
|
|
|
+echo "</html>";
|