Starting and Stopping
This simulation, indeed educational technology in general, is much more valuable when it can integrate with other content and interact with the user. A great first step in this direction is to add HTML controls to start and stop our simulation.
Each frame in our animation is generated by invoking requestAnimationFrame(nextFrame)
.
This produces a smooth animation because the last thing nextFrame
does is to issue another
requestAnimationFrame(nextFrame)
call, generating the next frame. To control this we introduce
a running
variable, and make the requestAnimationFrame
call only if
running
is true.
/**
* Run the simulation for n time steps, then show the results.
*/
function nextFrame() {
for (var i=0; i<nsteps; ++i) {
schrodinger.timestep();
}
renderer.show(schrodinger.getRenderedTexture());
if(running) {
requestAnimationFrame(nextFrame);
}
}
To start the simulation we set running
to true, and kick off the animation with a
call to requestAnimationFrame(nextFrame)
. To stop the animation, set running
to false. We usually make this available to the user through HTML controls such as a start and stop
buttons. Interestingly, Unicode has appropriate characters for both the start and
stop
buttons with corresponding HTML entities.
Setting up these buttons is probably a familiar process. Each button has a unique ID, which we use to lookup the button and attach an event listener.
<button id="start" class="setter">▸</button>
<button id="stop" class="setter">◼</button>
stopButton = document.getElementById("stop");
stopButton.addEventListener("click", toggleAnimation, false);
startButton = document.getElementById("start");
startButton.addEventListener("click", toggleAnimation, false);
We use the same event handler for both buttons. The toggleAnimation
handler
toggles the running
variable, and sets other variables according to the
new value for running
. If running
if true, it also calls
requestAnimationFrame(nextFrame)
to kick off the simulation.
/**
* Start/stop the simulation
*/
function toggleAnimation()
{
running = !running;
stopButton.disabled = !running;
startButton.disabled = running;
if (running)
{
requestAnimationFrame(nextFrame);
}
}
Each piece of code here is comparatively simple. Indeed, it is generally a good idea to tend to ward simpler code for clarity and maintainability. Complex applications can be built by assembling these simple building blocks.
