Snap object on scaling

by Hooman Askari

HTML

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

CSS

canvas {
    border: 1px solid #ccc;
}

JavaScript

var canvas = new fabric.Canvas('c'),
    grid = 50;

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

canvas.add(new fabric.Rect({
    left: 120,
    top: 240,
    width: 240,
    height: 100,
    fill: '#faa'
}));

canvas.on('object:scaling', function(options) {
    var target = options.target,
        w = target.getWidth(),
        h = target.getHeight(),
        snap = {   // Closest snapping points
            top: Math.round(target.top / grid) * grid,
            left: Math.round(target.left / grid) * grid,
            bottom: Math.round((target.top + h) / grid) * grid,
            right: Math.round((target.left + w) / grid) * grid
        },
        threshold = grid * 0.2,
        dist = {   // Distance from snapping points
            top: Math.abs(snap.top - target.top),
            left: Math.abs(snap.left - target.left),
            bottom: Math.abs(snap.bottom - target.top - h),
            right: Math.abs(snap.right - target.left - w)
        },
        attrs = {
            scaleX: target.scaleX,
            scaleY: target.scaleY,
            top: target.top,
            left: target.left
        };
    
    switch(target.__corner) {
        case 'tl':
            if (dist.left < dist.top && dist.left < threshold) {
                attrs.scaleX = (w - (snap.left - target.left)) / target.width;
                attrs.scaleY = (attrs.scaleX / target.scaleX) * target.scaleY;
                attrs.top = target.top + (h - target.height * attrs.scaleY);
                attrs.left = snap.left;
            }
            else if (dist.top < threshold) {
                attrs.scaleY = (h - (snap.top - target.top)) / target.height;
                attrs.scaleX = (attrs.scaleY / target.scaleY) * target.scaleX;
               ...