Draw on canvas

by PhilQ

HTML

<canvas class="real"></canvas>
<canvas class="overlay"></canvas>

SCSS

*, :before, :after { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
	width: 100%;
	height: 100%;
}

canvas {
	position: absolute;
	top: 0px;
	left: 0px;
	width: 100%;
	height: 100%;
	//background: #ccc;
	z-index: 1;
}
canvas.overlay {
	z-index: 2;
}

JavaScript

var $cnv,
	cnv,
	ctx,
	$cnv2,
	cnv2,
	ctx2,
	cnvWidth = 0,
	cnvHeight = 0,
	drawLineColor = '#000000',
	drawLineWidth = 8,
	drawOutlineColor = '#ffffff',
	drawOutlineWidth = 2,
	drawCurrentPath = [],
	draw_busy = false,
	drawMaxUndos = 5,
	drawUndoStates = [];

$( document ).ready(function() {

	$cnv = $('canvas.overlay');
	cnvWidth = $cnv.outerWidth();
	cnvHeight = $cnv.outerHeight();
	cnv = $cnv[0];
	cnv.width = cnvWidth;
	cnv.height = cnvHeight;
	ctx = cnv.getContext('2d');
	ctx.lineCap = "round";
	ctx.lineJoin = "round";
	ctx.lineWidth = drawLineWidth;
	ctx.strokeStyle = drawLineColor;
	
	$cnv2 = $('canvas.real');
	cnv2 = $cnv2[0];
	cnv2.width = cnvWidth;
	cnv2.height = cnvHeight;
	ctx2 = cnv2.getContext('2d');
	ctx2.lineCap = "round";
	ctx2.lineJoin = "round";
	ctx2.lineWidth = drawLineWidth;
	ctx2.strokeStyle = drawLineColor;
	
	$( window )
	.on('mousedown.startdraw touchstart.startdraw', function(ev) {
		//ev.preventDefault();
		//ev.stopImmediatePropagation();

		drawLine(ev.pageX, ev.pageY);

		$( window )
		.on('mousemove.draw touchmove.draw', function(ev2) {
			ev2.preventDefault();
			//ev2.stopImmediatePropagation();

			drawLine(ev2.pageX, ev2.pageY);
		})
		.on('mouseup.draw touchend.draw blur.draw mouseout.draw', function(ev2) {
			ev2.preventDefault();
			//ev2.stopImmediatePropagation();

			$( window ).off('.draw');
			endDrawLine();
		});

	})
	.on('keydown.undodraw', function(ev) {
		// Ctrl/Cmd + Z
		if (ev.which == 90 && (ev.metaKey || ev.ctrlKey)) {
			ev.preventDefault();
			drawUndo();
		}
	});

});

function drawUndo() {
	if (0 < drawUndoStates.length) {
		let ustate = drawUndoStates.pop();
		// Alternative: ctx.putImageData(ustate, 0, 0);
		let img = new Image();
		img.width = cnvWidth;
		img.height = cnvHeight;
		img.onload = function() {
			ctx2.clearRect(0, 0, cnvWidth, cnvHeight);
			ctx2.drawImage(img, 0, 0);
			draw_busy = false;
			// no longer need to read the blob so it's...