Javascript canvas drag-and-zoom library

Created: — modified: — tags: javascript

For those cases when you need to implement something GoogleMaps-like

Working on some project I had to implement a intuitive navigation on the canvas. This library provides exactly that. Use it like this:

<!DOCTYPE html><html><body>
<canvas id="canvas" width="500" height="500" style="border:1px solid #d3d3d3;"></canvas>

<script src="scroll.js"></script>
<script>

    function draw(options){
            options.ctx.beginPath();
            options.ctx.arc(95, 50, 40, 0, 2 * Math.PI);
            options.ctx.stroke();
        }

    new CanvasDragZoom(document.getElementById('canvas'), draw);

</script></body></html>

In other words:

The draw function should accept a single options argument, which is a JSON object with various key-value pairs, most important of which is a ctx key, which is this canvas'es 2d context. In other words, the thing that you draw on. And you will get something like this:

Options

Other options in the object passed to the draw function are:

Perlin noise example

Example showing usage of these parameters explores Perlin noise generated by this nice Joseph Gentle library. Here is the code:

<!DOCTYPE html><html><body>
<canvas id="canvas" width="500" height="500" style="border:1px solid #d3d3d3;"></canvas>

<script src="scroll.js"></script>
<script src="perlin.js"></script>
<script>

    var image, data;

    function draw(options){
        if(!data){
            // reuse this temporary imageData object
            image = options.ctx.createImageData(options.width_px, options.height_px);
            data = image.data;
        }

        for (var x_px = 0; x_px < options.width_px; x_px++) {
            // convert from "screen pixel" to "canvas units" for x
            var x = x_px/options.scale + options.minx;
            for (var y_px = 0; y_px < options.height_px; y_px++) {
                // convert from "screen pixel" to "canvas units" for y
                var y = y_px/options.scale + options.miny;

                // calculate noise value at point (x,y)
                var value = noise.perlin2(x / 200, y / 200)/2+0.5;
                value *= 256;

                // put value onto image. Note that imageData object uses "screen pixel"
                // coordinates, so it's not affected by zoom or transition effects.
                var cell = (x_px + y_px * canvas.width) * 4;
                data[cell] = data[cell + 1] = data[cell + 2] = value;
                data[cell + 3] = 255; // alpha.
            }
        }
        options.ctx.putImageData(image, 0, 0);
    }

    new CanvasDragZoom(document.getElementById('canvas'), draw);

</script></body></html>

And that's how it looks:

Triangulation example

Last example lets you explore infinite delaunator triangulation. Sorry, the code is too big to fit in this blog post - so view the source of the frame below if you're interested!

Acknowledgements

Thanks to this SO answer for original implementation.