Capturing Snapshots
Snapshots are great for capturing features of a simulation for detailed discussions, inclusion in homework problems or a book, or even sharing on social media.
Adding snapshots is a great opportunity to foray into custom elements1. We
added the canvas-snapshooter
element, and the snapshot-caption
element. Together these define a button to take a snapshot, and the caption for that snapshot.
Snapshots are absolutely positioned above the other content. They can also be minimized, and dragged to reposition them anywhere on the page.
We see how it all comes together if we look at the figure
containing
the visualization. Keep in mind that we also pass "results" to the Schrödinger simulation.
The simulation knows to display itself in this figure, and to listen for "results"
snapshot events.
<figure class="center" id="results">
<!-- Results canvas will be inserted here -->
<div class="buttonContainer">
<button id="start">▶<br/>Play</button>
<button id="stop">■<br/>Stop</button>
<button data-bc="true" class="launcher">↺<br/>Restart</button>
<canvas-snapshooter target="results">
<snapshot-caption>Snapshot at time ${time}.</snapshot-caption>
</canvas-snapshooter>
</div>
<figcaption>
Now we can capture images of our simulations.
</figcaption>
</figure>
The caption is evaluated as a
JavaScript template
when each snapshot is generated. In this case we have a global variable, time
, on the page so
${time}
is replaced with the time
value for each snapshot. The caption identifies
how far into the simulation the image was captured.

We can clean this up a bit. Looking at the code, dt = 5.0E-07
, we see that
there are at most 6 decimal places of significance. Figures beyond this are simply numerical
noise from the imprecise representation of decimal fractions as a binary number.
JavaScript templates let us embed any JavaScript expression, so we can use
${time.toFixed(6)}
to finesse the displayed time value.
<snapshot-caption>Snapshot at time ${time.toFixed(6)}.</snapshot-caption>

We can even go a little further. As the Schrödinger solver evolves, time
will
be moved to an internal state, and no longer be available as a global variable. We will be
sure to keep time
available through a getter. Our caption will then be something
like this:
<snapshot-caption>Snapshot at time ${renderer.getTime().toFixed(6)}.</snapshot-caption>

- Custom elements have been around for a while, but now they are broadly supported.