JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="600" height="600"></canvas>
<button>Dorito</button>

CSS

canvas {
    border: 1px solid #ccc;
}

JavaScript

var canvas = new fabric.Canvas('c', {
  selection: false
});
var grid = 50;

for (var i = 0; i < (600 / grid); i++) {
  canvas.add(new fabric.Line([i * grid, 0, i * grid, 600], {
    stroke: '#ccc',
    selectable: false
  }));
  canvas.add(new fabric.Line([0, i * grid, 600, i * grid], {
    stroke: '#ccc',
    selectable: false
  }))
}

canvas.add(new fabric.Rect({
  left: 100,
  top: 100,
  width: 50,
  height: 50,
  fill: '#faa',
  originX: 'left',
  originY: 'top',
  centeredRotation: true
}));

canvas.add(new fabric.Circle({
  left: 300,
  top: 300,
  radius: 50,
  fill: '#9f9',
  originX: 'left',
  originY: 'top',
  centeredRotation: true
}));

canvas.on('object:moving', function(options) {
  options.target.set({
    left: Math.round(options.target.left / grid) * grid,
    top: Math.round(options.target.top / grid) * grid
  });
});

canvas.on("object:modified", function(modEvtData) {
  var modifiedObj = modEvtData.target;
  if (modifiedObj.angle) {
    modifiedObj.straighten();
    canvas.renderAll();
  }
});

/*
canvas.on("object:modified", function(modEvtData) {
  var modifiedObj = modEvtData.target;
  if (modifiedObj.angle && snapAfterRotate) {
    modifiedObj.setAngle(lastClosestAngle).setCoords();
    snapAfterRotate = false;
    canvas.renderAll();
  }
});

var lastClosestAngle = 0;
var snapAfterRotate = false;

function calculateClosestAngle(targetObj) {
  var currentAngle = targetObj.angle.toFixed(0);
  snapAfterRotate = true;
  if (currentAngle >= 45 && currentAngle < 135) {
    return 90;
  } else if (currentAngle >= 135 && currentAngle < 225) {
    return 180;
  } else if (currentAngle >= 225 && currentAngle < 315) {
    return 270;
  } else if ((currentAngle >= 315 && currentAngle <= 360) || (currentAngle >= 0 && currentAngle < 45)) {
    return 0;
  }
  return currentAngle;
}

canvas.on("object:rotating", function(rotEvtData) {
  var targetObj = rotEvtData.target;
  lastClosestAngle = calculateClosestAngle(targetObj);
});
*/