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.