Fabric - snapping setup

by STHayden

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.4/fabric.min.js"></script>
<canvas id="c" width="600" height="600"></canvas>

CSS

canvas {
    border: 1px solid #ccc;
}

JavaScript

window.canvas = new fabric.Canvas('c', { selection: false, preserveObjectStacking:true });

fabric.util.object.extend(fabric.Canvas.prototype, {
  _rotateObjectWithOutSnappig: fabric.Canvas.prototype._rotateObject,
  _rotateObject: function(x, y) {
    this._rotateObjectWithOutSnappig(x, y);
    var t = this._currentTransform;

    if (typeof t.target.snapAngle !== 'number') { return; }

    var angle  = t.target.angle;
    var snapAngle  = t.target.snapAngle;
    var snapThreshold  = t.target.snapThreshold || snapAngle;
    var rightAngleLocked = Math.ceil(angle / snapAngle) * snapAngle;
    var leftAngleLocked = Math.floor(angle / snapAngle) * snapAngle;

    if (Math.abs(angle - leftAngleLocked) < snapThreshold) {
      t.target.angle = leftAngleLocked;
    } else if (Math.abs(angle - rightAngleLocked) < snapThreshold) {
      t.target.angle = rightAngleLocked;
    }

    return this;
  }
});

var rect = new fabric.Rect({ 
  left: 100, 
  top: 100, 
  width: 50, 
  height: 50,
  snapAngle: 45,
  fill: 'red', 
});
rect.on('rotating', function(options) {
	if(options.e.shiftKey) {
  	this.previousSnapAngle = this.snapAngle;
  	this.snapAngle = 0;
  } else {
  	this.snapAngle = this.previousSnapAngle;
    delete this.previousSnapAngle;
  }
});
canvas.add(rect);

canvas.add(new fabric.Rect({ 
  left: 200, 
  top: 200, 
  width: 50, 
  height: 50,
  snapAngle: 45,
  snapThreshold: 10,
  fill: 'green', 
}));