LoopController
by Laurens Maneschijn
HTML
<div id="Demo">
<div id="loopcontrols"></div>
draw circle:
<input id="drawcircle" type="checkbox">
repeat to simulate load:
<input id="drawcircle_repeat_n" type="range" value="1" min="1" max="50001" step="1000">
<hr>
<pre id="log"></pre>
<canvas id="canvas" style="display: none;"></canvas>
</div>
<div id="Demo2">
<hr>
<button onclick="new Demo2()">add Demo2 loop</button>
<hr>
</div>
CSS
.loopcontrollerinterface button {
text-align: center;
vertical-align: middle;
margin: 2px;
min-height: 28px;
min-width: 28px;
/* aspect-ratio: 1/1;*/
}
.loopcontrollerinterface button.active {
background-color: #ddd;
border-width: 2px;
}
input[type="range"] {
position: relative;
margin-bottom: 6px;
}
input[type="range"]::after {
content: attr(title);
position: absolute;
z-index: 9;
top: 12px;
}
.Demo2 {
border: 1px solid #8888;
margin: 2px;
padding: 2px;
}
JavaScript
console.clear();
// TODO: implement private and public things (jsfiddle doesn't support the syntax though)
class LoopController {
constructor() {
this.initevents();
this.loopfunction = function(loop) {};
this.running = false;
this.run_once = false;
this.last_request = null;
this.setDelay(16); // delay 16 = 62.5 FPS
this.reset();
}
reset() {
this.event('resetting');
this.timestamp_start = null;
this.timestamp_last = null;
this.framecount = 0;
this.total_runtime_ms = 0;
this.frametimes = [];
this.frametimes_i = 0;
this.frametimes_max = 10;
this.total_loopfunction_time = 0;
this.event('reset');
}
toggle() {
this.event('toggling');
if (this.running) {
this.stop();
} else {
this.start();
}
this.event('toggled');
}
stop() {
if (!this.running) {
return;
}
this.event('stopping');
this.running = false;
cancelAnimationFrame(this.last_request);
this.last_request = null;
this.timestamp_last = null;
this.event('stopped');
}
start() {
if (this.running) {
return;
}
this.event('starting');
this.running = true;
cancelAnimationFrame(this.last_request);
this.last_request = requestAnimationFrame(this._step.bind(this));
this.event('started');
}
step() {
if (this.running) {
return;
}
this.event('stepping');
this.run_once = true;
this.start();
}
setLoopFunction(loopfunction) {
if (typeof loopfunction !== 'function') {
throw Error('LoopController setLoopFunction() no function given.');
}
this.loopfunction = loopfunction;
this.event('loopfunction_changed');
}
setDelay(delay) {
if (typeof delay === 'string') {
delay = parseFloat(delay);
}
if (typeof delay !== 'number' || Number.isNaN(delay)) {
throw Error('LoopController setDelay() : no number given.');
}
var oldvalue = this.delay;
this.delay = delay;
if (delay !== oldvalue) {
this.event('delay_changed');
}
}
setFPS(fps) {
if (typeof fps === 'string') {
fps =...