D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
njvack
Full window
Github gist
Blinken
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <script type="text/javascript"> window.console = window.console || {} window.console.log = window.console.log || function() {}; console.log("Hello"); // Standard sum function function sum(ar) { return ar.reduce(function(s, val) { return s + val; }, 0) } // Numerical mean function mean(ar) { return sum(ar) / ar.length; } function avg_square_diffs(ar) { var m = mean(ar); var sqdiffs = ar.map(function(e) { var d = e - m; return d * d; }); return mean(sqdiffs); } // Yup, it's standard deviation function stdev(ar) { return Math.sqrt(avg_square_diffs(ar)); } var blink_controller = function(cycle_ms, blink_ms, blink_element, record_blinks) { var my = {}; my.cycle_ms = cycle_ms; my.blink_ms = blink_ms; my.blink_element = blink_element; my.record_blinks = record_blinks; my.blinks_recorded = 0; my.event_list = []; my.keep_blinking = false; my.started = false; my.finished = false; function blink_on() { my.blink_element.classList.add("on"); if (my.started) { my.blinks_recorded += 1; console.log(my.blinks_recorded); } } function blink_off() { my.blink_element.classList.remove("on"); if (my.blinks_recorded >= my.record_blinks) { my.finished = true; my.stop_blinking(); var evt = new Event('finish'); my.blink_element.dispatchEvent(evt); } } function record_blink(timestamp) { my.event_list.push({ "type": "blink_on", "timestamp": timestamp, }); } var handle_frame = function(timestamp) { // console.log("in handle_frame...") if (my.keep_blinking) { my.last_frame_time = my.last_frame_time || timestamp; var elapsed = timestamp - my.last_frame_time; // console.log([elapsed, my.blink_remaining, my.cycle_remaining].join("\t")); if (isFinite(my.blink_remaining)) { my.blink_remaining -= elapsed; } if (my.blink_remaining <= 0) { blink_off(); my.blink_remaining = NaN; //my.event_list.push(["blink_off", timestamp]) console.log("blink_off\t"+timestamp); } my.cycle_remaining -= elapsed; if (my.cycle_remaining <= 0 ) { blink_on(); my.blink_remaining = my.blink_ms; my.cycle_remaining = my.cycle_ms; my.event_list.push( { "type": "blink_on", "timestamp": timestamp }); console.log("blink_on\t"+timestamp); } my.last_frame_time = timestamp; if (my.keep_blinking) { window.requestAnimationFrame(handle_frame); } } } my.start_blinking = function() { my.keep_blinking = true; my.cycle_remaining = my.cycle_ms; my.blink_remaining = my.blink_ms; window.requestAnimationFrame(handle_frame); } my.stop_blinking = function() { my.keep_blinking = false; } function make_sort_function(evt) { return function(ke1, ke2) { var dist1 = Math.abs(evt.timestamp - ke1.timestamp); var dist2 = Math.abs(evt.timestamp - ke2.timestamp); return dist1 - dist2; }; } function get_blink_events() { return my.event_list.filter(function(e) { return e.type == 'blink_on'; }); } function get_press_events() { return my.event_list.filter(function(e) { return e.type == 'keypress'; }); } my.match_blinks_and_presses = function() { var blinks = get_blink_events(); var bs = blinks.slice(); var presses = get_press_events(); console.log(presses); presses.forEach(function(p) { console.log("Finding closest blink..."); console.log(p); var sort_fx = make_sort_function(p); bs.sort(sort_fx); console.log(p); var b = bs[0]; console.log("Closest match:"); console.log([p.timestamp, b.timestamp]); b.press_candidate = b.press_candidate || p; var old_diff = Math.abs(b.timestamp, b.press_candidate.timestamp); var new_diff = Math.abs(b.timestamp, p.timestamp); if (new_diff < old_diff) { b.press_candidate = p; } }); console.log(blinks); return blinks.filter(function(b) { return b.press_candidate; }).map(function(b) { return { "blink": b, "press": b.press_candidate, "diff": b.press_candidate.timestamp - b.timestamp } }); } function record_press(timestamp) { my.event_list.push({ "type": "keypress", "timestamp": timestamp }); } my.handle_press = function(event) { console.log(event); if (my.finished) { return; } if (!my.started) { console.log("starting to record"); my.started = true; } record_press(window.performance.now()); } return my; } window.addEventListener('load', function() { console.log("Loaded"); var blink_elt = document.getElementById('blinker'); var record_blinks = 14; var blinks_per_minute = 60; var cycle_ms = (60 * 1000) / blinks_per_minute; var blink_ms = (6/60) * 1000; window.bc = blink_controller(cycle_ms, blink_ms, blink_elt, record_blinks); document.addEventListener('keydown', bc.handle_press); blink_elt.addEventListener('finish', function(e) { var res = bc.match_blinks_and_presses(); var diffs = res.map(function(thing) { return thing.diff; }); document.getElementById("results").innerHTML = diffs.join("\n"); var m = mean(diffs); var s = stdev(diffs); document.getElementById("mean").innerHTML = "Mean: " + m; document.getElementById("std").innerHTML = "Stdev: " + s; }); bc.start_blinking(); }); </script> <style type="text/css"> #blinker { width: 200px; height: 200px; border-radius: 100px; margin: 32px; } #blinker.on { background-color: red; } </style> </head> <body> <div id="blinker" class="on"> </div> <p>Press space when it blinks!</p> <pre><div id="results"></div></pre> <h3 id="mean"></h3> <h3 id="std"></h3> </body> </html>