Using double buffering to get live updating math with MathJax
One very important topic to Jon and myself is making math look good everywhere we need to render it. This is reasonably straight-forward with static math (with some unfortunate caveats) but what about math that updates in response to user action?
For this post the example we'll be looking at is very simple. It's just a text field and a div. The desired behavior is that as the user types AsciiMath [LINK] expressions into the box, the updates are rendered live into the div. Here’s the HTML snippet for that:
By default, Mathjax just renders the math present on the page at the time when mathjax loads. We need to explicitly ask mathjax to render the new math when it updates.
Let's take a look at what a naive implementation of dynamically rendering the user's input looks like.
This is hard to make look good. The annoyance of the popping effect depicted in the link above is magnified about 1000 fold when it's happening live as you type.
How can we improve on this?
Obviously this is not an acceptable solution. But what is causing this and what can we do to improve it?
The problem is that by default, most configurations of mathjax do a fast preview pass before rendering the full version. If you can believe it, turning fast preview off entirely makes it look even worse since the math disappears altogether between updates:
Essentially, what we want to do is tell mathjax to render the new math without getting rid of the last math.
As the title suggests, we're going to be using a technique from computer graphics called double buffering which does just that.
Double buffering
In computer graphics, you have two buffers which represent the screen. While one buffer is being shown to the users, the computer draws the next frame into the other buffer. Once it's done drawing, it can quickly swap the new buffer to the screen providing the user with a seamless experience.
Getting back to our previous example, our two “buffers” in this case, are going to be two divs that we’ll ask Mathjax to render into. So in terms of the structure of the HTML, this is what that looks like:
When one div is presented to the user and the user updates with field, we ask mathjax to render the new math into the hidden div. Then once mathjax indicates it's done rendering we hide the one div and show the newly rendered div.
Here's the updated code:
And this is how it looks:
Future improvements
Using double buffering was a big improvement for the interactivity of the page. One further enhancement I'm thinking about is rendering the math as you type, for example, how to get the math to render in the text field itself.
But for now, the irritation factor is low enough I wouldn't object to having this on the site.
Rest assured, if I figure out how to implement a text field like Desmos’, I'll be back with another post!