High Performance JS heatmaps

Feb. 04, 2013
comments

You might have encountered heatmaps for data visualization before. There is a fabulous library, heatmap.js, which brings that capability to draw them to javascript. There is only one problem, it is not exactly fast. Sometimes that doesn't matter. But if you have hundreds of thousands of data points to plot, or need realtime performance, it gets tricky. To solve that I've written a little engine using WebGL for drawing heatmaps.

Update:

Contents

Screenshot

Live Version

The mouse movement is used to draw the map in realtime. Click into the canvas to erase it.

Performance

You can draw around 500'000 individual data points per second in realtime. Around 10'000 per frame are no problem. The way it works is that points to draw are recorded into a position buffer (10k points) and when you call heatmap.update() (or when the buffer is full) it draws these points with WebGL by additively blending them into an off-screen floating point texture.

Quality

The heat is updated/recorded as a height in an off-screen floating point texture. Conversion to a color display is done as a second step. Due to this mechanism the quality is fairly good (compared to methods using byte precisions).

Usage

Instantiate a new heatmap, errors can be one of:

  • "Webgl is not supported"
  • "No floating point texture support"
  • "Floating point render target not supported"
  • "Shader Compile Error: ..."
  • "Shader Link Error: ..."
try{
    var heatmap = createWebGLHeatmap({canvas: yourCanvas});
}
catch(error){
    // handle the error
}

Add a data point.

  • x and y relative to the canvas in pixels
  • size in pixels (radius)
  • intensity between 0 and 1
heatmap.addPoint(x, y, size, intensity);

Draw queued data points:

heatmap.update()

Display the heatmap

heatmap.display()

Multiply all values in the heatmap by a number (useful for decay)

heatmap.multiply(0.995)

Clamp all values in the heatmap to between two values:

heatmap.clamp(0.0, 1.0)

Blur all values a little:

heatmap.blur()

Sourcecode

You can find the code for the library and an example page on github.

Caveats

Due to this being WebGL it will not run for everybody (please consult the statistics page for up to date numbers).

It also requires floating point textures and floating point texture render targets, which not everybody has.

There might also be problems with shaders on certain platforms.