Skip to main content

Section 14 Interactive Elements, Authored

When outputting Web page versions, it is possible to embed a variety of dynamic interactive elements. In a /PDF version, these will necessarily need to be replaced by some static substitute, such as a screenshot. See Section 3 for the specifics of embedding instances of the Sage Cell Server, which is more elaborate, and not entirely similar.

Interactives in this section are those for which you provide code you have authored. Generally, the libraries involved to support this have open licenses, though the player for GeoGebra may be an exception. Creating these assumes some familiarity with HTML and Javascript. See Section 15 for more interactives that are perhaps simpler to create or use.

(2018-06-22) Almost everything in this section is under active development and not stable yet. Feel free to experiment and make suggestions and requests. This page takes a while to completely load, so be patient.

Subsection 14.1 HTML5 Canvas

HTML5 introduced the <canvas> element, which can be thought of a blank slate, a place to draw or write on. So PreTeXt has the <slate> element for a similar purpose. Generally, but not exclusively, HTML5 writes on a <canvas> using the Javascript language. We demonstrate this approach to interactive diagrams in this subsection.

The following examples are from David Austin's excellent Understanding Linear Algebra textbook, which can be found at

David's contribution of examples, and assistance designing the PreTeXt elements is greatly appreciated. Alright, let's learn some linear algebra. Yes, there are some learning opportunities in this subsection.

Let \(\vec{x}\) be represented by the red arrow, and \(A\vec{x}\) by the grey arrow, for some particular \(2\times 2\) matrix \(A\text{.}\) Drag the tip of the red arrow to see the grey arrow change.

Figure 14.1 A simple eigenvector demonstration

The interactive in Figure 14.1 shows a vector \(\vec{x}\) in red, and the matrix-vector product \(A\vec{x}\) in grey, for a particular \(2\times 2\) matrix \(A\text{.}\) The four entries of the matrix \(A\) are coded into the interactive. Can you deduce \(A\) simply by using the interactive? Which theorem is the key?

Let \(\vec{x}\) be represented by the red arrow, and \(A\vec{x}\) by the grey arrow, for a \(2\times 2\) matrix \(A\text{.}\) Drag the tip of the red arrow to see the grey arrow change. Or drag the blue sliders to change the numerical values of the four entries of the \(2\times 2\) matrix \(A\text{.}\) You will not see the grey vector until you change the matrix using one of the two sliders on the left. Why is that? What are the eigenvectors of the initial matrix?

Figure 14.3 Eigenvector demonstration

The next example has ten <slate> elements communicating with each other, and arranged with the layout features of a <sidebyside> (see Section 22).

Parameters \(a\text{,}\) \(b\text{,}\) \(d\text{,}\) and \(e\text{,}\) form a \(2\times 2\) matrix \(A\text{,}\) while \(c\) and \(f\) form a vector \(\vec{b}\text{.}\) The two views of Woody shows the effect of the mapping

\begin{equation*} \vec{x}\mapsto A\vec{x} + \vec{b}\text{.} \end{equation*}
Figure 14.4 Affine Transformations

Subsection 14.2 D3.js

D3 is a Javascript library for “Data-Driven Documents”, which might greatly enhance some data you wish to display. In short, it uses the animation capabilities of SVG. Available examples seem sensitive to the version of the library, so we have examples using different versions. Use the @version attribute on <interactive> to specify the version number. The default is 5.

The first example uses the force layout and collision detection from Version 3. (The necessary commands are very different in Version 4.) Pretend you are a working shepherding dog. Can you separate, and catch, one of the herd?

This is adapted from a block by Mike Bostock at 3231298 with a GPL license. A similar demonstration, only using an HTML5 canvas is at

Place your mouse/pointer at the center of the interactive to repel the 200 circles.

Figure 14.5 Force layout and collision detection

Similar, but different, this demonstration of a graph layout uses Version 4 of the library. Technical notes:

  • We have changed the size of the nodes, and their number, to fit in a smaller space.
  • The Javascript script uses introspection to size itself, which would be a good general practice.

This is adapted from a block by shimizu at e6209de87cdddde38dadbb746feaf3a3 with a GPL license.

Drag a vertex to a new location to see the graph adjust its layout.

Figure 14.6 Graph Layout

Can you move the vertices to new locations such that the resulting graph is planar? (In other words, no edges cross?)

Finally an example that actually uses some data. Here is the description from the original block by Martin Chorley at 7aa53c7bf3e411238ac8aef280bd6581, provided with an MIT License.

This visualisation uses a D3 force simulation to show the Twitter relationships between the Assembly Members in the Welsh Assembly in terms of the number of times each assembly member has mentioned another assembly member in a tweet.

Twitter relationships were mined on 22/03/2017, and are representative of the conversational relationships on that date. Links between AMs represent a conversational relationship: one AM has mentioned the other. Party colour indicates the direction of the mention.

Hover over the nodes to fade out non-connected nodes.

Rather than using intermediate nodes to create curved links (as in Mike Bostock's block), this adds curves by adding a calculated control point for each edge.

Technical notes:

  • Once the nodes organize themselves (automatically in the beginning), they cannot be moved.
  • We have adjusted the margins in an attempt to keep names visible on the right side, but without giving up too much space.
  • We have adjust the repelling force, and the collision buffer, to better fit the available space.
  • This example required its own CSS, which we have included as part of the <interactive>.
  • The data collected from the Twitter analysis is contained in a JSON file, mention_network.json, and where the script loads that file, it needs a path relative to the HTML file where the interactive is viewed.

Hover on the name of an Assembly Member to concentrate on their tweet mentions.

Figure 14.8 Tweet mentions within the Welsh Assembly

Subsection 14.3 SVG

Entirely similar to using an HTML5 canvas element (14.1), it is possible to control an SVG element with Javascript. This example is from Mark McClure.

Select a function with the radio buttons, then use the checkbox to add the secant line. The denominator of the difference quotient, \(h\text{,}\) can be adjusted with the slider and the red point will react to the different values. The green point is the point of tangency, and can be dragged with the mouse.

Figure 14.9 Tangent and secant slopes

When discussing the derivative as a limit, we think of the point of tangency as being fixed (the green point in 14.9) and the “other” point defining the secant line as changing (the red point in 14.9). Switch it up! Fix a large value of \(h\) (positive or negative) and then change the point of tangency (the green point). Discuss what you observe.

Subsection 14.4 JSXGraph

JSXGraph is a “cross-browser JavaScript library for interactive geometry, function plotting, charting, and data visualization in the web browser.” Now a <slate> will be what JSXGraph calls a board. Again, you use Javascript to write onto a <slate>, but have some powerful shortcuts available from the JSXGraph library. For this reason, PreTeXt calls JSXGraph a “language”, similar in may respects to how Sage is a language, but is really a Python library. So realize that the syntax for using JSXGraph is that of Javascript.

Place Javascript inside a file that is specified with the @source attribute of the <interactive> element. Then just be certain that @xml:id of the <interactive> element is passed as the HTML id in an (early) call to JSXGraph's initBoard() method.

The plot below is the curve \(r=a+b\theta\) in polar coordinates, for \(0\leq\theta\leq 8\pi\text{.}\) It may be manipulated with the sliders to control the shape of the curve. Point \(A\) is contrained to the curve, but may be dragged to a new location. At \(A\) the tangent line and normal line are plotted as dashed red lines. Use the controls in the lower left to adjust the viewing window. This example is taken from the JSXGraph example wiki. The code could be written in 7 lines. Width is 80% and aspect ratio is 4:3.

Drag the sliders to change the parameters \(a\) and \(b\text{.}\) Controls in the lower-right will adjust the viewing window.

Figure 14.14 The Archimedian Spiral \(r = a + b\theta\text{,}\) \(0\leq\theta\leq 8\pi\)

Here is a more elaborate example, from the JSXGraph Showcase, titled Infinity.

There are two active sliders to control the shape and shading of the graphic, and hovering the mouse near one of the edges will highlight the entirety of one of the 30 quadrangles. Finally, each of the four red corners may be dragged to a new location. Code is 47 lines. Width is 60% and aspect ratio is the default, 1:1, i.e. a square.

Drag the sliders to change the pattern, and drag any of the four red corners to change the overall shape.

Figure 14.15 Infinity, from the JSXGraph Showcase

Here are the two new examples. They have been included in a sidebyside layout element with equal widths (see Section 22) so they can be placed horizontally across the page. They are not wrapped as figures, so cannot be cross-referenced. These are again from the example wiki, the left being Fermat's Spiral and the right being a demonstration of B-splines.

Drag the slider to change the curve.

Any of the 8 red control points may be moved anywhere.

Finally, a piecewise function you can control, with traces of the domain values and range values in two other JSXGraph boards. Boards and HTML buttons have been laid out using the sidebyside layout element.

The slider of the left panel will trace out the piecewise function. Simultaneously, the domain will be traced in the middle panel, and the range in the right panel.

Figure 14.16 Piecewise Function

Generally, we load an interactive into an HTML iframe to sandbox (isolate) it from other interactives. We does this for your own protection. So, for example, one interactive cannot talk to another. If two <slate> need to communicate, then they are related, and should be placed into a single <interactive>, allowed to layout themselves, or grouped within a <sidebyside> allowing finer control. Even if we have this under control, you might still enjoy reading Your JS is a Mess at

Subsection 14.5 Sage Interacts

Sage, and the Sage Cell Server, support interactive demonstrations, called interacts.

  • The interactive elements are nearly trivial to construct.
  • An interact is simply a single Python function (acted on by a decorator).
  • You have the full mathematical power of Sage at your disposal, so can do some very powerful computations with high precision (or exactly).
  • The interface is not as polished as what you can achieve with Javascript libraries.
  • Graphics refresh with a round-trip to the server, so are not nearly as fluid as with other tools.

Note that each interact is insulated from the others, unlike our other employment of the Sage Cell Server.

This example is by Marshall Hampton, taken from the Sage interact wiki,, specifically here.

Figure 14.17 Numerical integrals using the midpoint rule

Subsection 14.6 Geogebra

Better than using the server version of Geogebra might be designing your own material, retaining your copyright, and using one of Geogebra's “Apps” to embed the material in your document. (But note, use of the App comes with licensing restrictions.) PreTeXt will handle the technical details for you.

  1. Use Geogebra to make a material. Maybe you need to install a desktop program that allows you to do this. Then export, or otherwise discover the “base64-encoded” version which may be identified by ggb. See the source of this page for examples of what this looks like.
  2. Mimic the source of the examples below.
  3. Long-run it will be better to park these strings in files (in a code subdirectory?) and <xi:include> them with the @parse attribute set to text. But we do not want to impede a newcomer's quickstart with the problematic -xinclude switch.

The sliders on the next applet seem to be at fixed locations. Make it too skinny and you will never see them, rendering the material useless. However the window will pan (drag with a mouse) and zoom (scroll wheel of a mouse), so you can adjust that way.

Figure 14.18 GeoGebra: astroids (from Dave Rosoff)

Now the controls are in the upper-left corner, so we can more easily make the window a little smaller. Pan and zoom to put the action where you can see it better.

Figure 14.19 GeoGebra: cycloids (from Dave Rosoff)

You will need to zoom out a bit, and then pan over some, to see all the pieces of the next GeoGebra material.

Drag some of the points and some of the circles to change them, and watch the remainder react.

Figure 14.20 GeoGebra: a constructive “proof” that SAS congruence holds in Euclidean geometry (from Tevian Dray)