FabricJS cropzoom demo

by dudi do

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.0/fabric.min.js"></script>
<h1>FabricJS cropzoom demo</h1>
<div id="canvasContainer">
<canvas id="c" width="400" height="400"></canvas>
</div>
<br>
<button type="button" onclick="demo.zoomBy(0,0,10)">Zoom in</button>
<button type="button" onclick="demo.zoomBy(0,0,-10)">Zoom out</button>
<button type="button" onclick="demo.zoomBy(-5,0,0)">&#8592;</button>
<button type="button" onclick="demo.zoomBy(0,-5,0)">&#8593;</button>
<button type="button" onclick="demo.zoomBy(0,5,0)">&#8595;</button>
<button type="button" onclick="demo.zoomBy(5,0,0)">&#8594;</button>
<hr>
Keyboard shortcuts:
<table>
<tr><td class="key"><span>&#8592; &#8593; &#8595; &#8594;</span></td><td>Move object</td></tr>
<tr><td class="key"><span>[CTRL] &#8592; &#8594;</span></td><td>Rotate object</td></tr>
<tr><td class="key"><span>[CTRL] + -</span></td><td>Zoom in/out</td></tr>
<tr><td class="key"><span>[SHIFT] &#8592; &#8593; &#8595; &#8594;</span></td><td>Crop-move object</td></tr>
</table>

<div id="base64"...

CSS

body {
	font: 11pt Arial, Helvetica;
}

#canvasContainer {
	background-image: url(data:image/gif;base64,R0lGODlhCgAKAIAAAOLi4v///yH5BAAHAP8ALAAAAAAKAAoAAAIRhB2ZhxoM3GMSykqd1VltzxQAOw==);
	display: inline-block;
	border: 2px solid #ccc;
}

.key>span {
	background: #428bca;
	border-radius: 3px;
	color: white;
	font-size: 9pt;
	padding: 2px;
}

JavaScript

fabric.Cropzoomimage = fabric.util.createClass(fabric.Image, 
{
	type: 'cropzoomimage',
	zoomedXY: false,
	initialize: function(element, options) 
	{
		options || (options = {});
		this.callSuper('initialize', element, options);
		this.set({
			orgSrc: element.src,
			cx: 0, // clip-x
			cy: 0, // clip-y
			cw: element.width, // clip-width
			ch: element.height // clip-height
		});
	},

	zoomBy: function(x, y, z, callback) 
	{
		if (x || y) { this.zoomedXY = true; }
		this.cx += x;
		this.cy += y;

		if (z) {
			this.cw -= z;
			this.ch -= z/(this.width/this.height);
		}

		if (z && !this.zoomedXY) { 
			// Zoom to center of image initially
			this.cx = this.width / 2 - (this.cw / 2);
			this.cy = this.height / 2 - (this.ch / 2);
		}

		if (this.cw > this.width) { this.cw = this.width; }
		if (this.ch > this.height) { this.ch = this.height; }
		if (this.cw < 1) { this.cw = 1; }
		if (this.ch < 1) { this.ch = 1; }
		if (this.cx < 0) { this.cx = 0; }
		if (this.cy < 0) { this.cy = 0; }
		if (this.cx > this.width - this.cw) { this.cx = this.width - this.cw; }
		if (this.cy > this.height - this.ch) { this.cy = this.height - this.ch; }

		this.rerender(callback);
	},

	rerender: function(callback) 
	{
		var img = new Image(), obj = this;
		img.onload = function() {
			var canvas = fabric.util.createCanvasElement();
			canvas.width = obj.width;
			canvas.height = obj.height;
			canvas.getContext('2d').drawImage(this, obj.cx, obj.cy, obj.cw, obj.ch, 0, 0, obj.width, obj.height);

			img.onload = function() {
				obj.setElement(this);
				obj.applyFilters(demo.canvas.renderAll.bind(demo.canvas));
				obj.set({
					left: obj.left,
					top: obj.top,
					angle: obj.angle
				});
				obj.setCoords();
				if (callback) { callback(obj); }
			};
			img.src = canvas.toDataURL('image/png');
		};
		img.src = this.orgSrc;
	},

	toObject: function()
	{
		return fabric.util.object.extend(this.callSuper('toObject'), {
			orgSrc: this.orgSrc,
			cx: this.cx,
			cy: this.cy,
			cw:...