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.