Fabric JS - objects snapping, no overlap

by 20yco

HTML

<canvas id="canvas" width="800" height="500" style="border:1px solid #ccc"></canvas>

JavaScript

var canvas = new fabric.Canvas('canvas'),
canvasWidth = document.getElementById('canvas').width,
canvasHeight = document.getElementById('canvas').height,
counter = 0,
rectLeft = 0,
snap = 20; //Pixels to snap

canvas.selection = false;
plusrect();
plusrect();
plusrect();

function plusrect(top, left, width, height, fill) {
	var rect = new fabric.Rect({
		top: 300,
		name: 'rectangle ' + counter,
		left: 0 + rectLeft,
		width: 100,
		height: 100,
		fill: 'rgba(' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ', 0.75)',
		lockRotation: true,
		originX: 'left',
		originY: 'top',
		cornerSize: 15,
		hasRotatingPoint: false,
		perPixelTargetFind: true,
		minScaleLimit: 1,
		maxWidth: canvasWidth,
		maxHeight: canvasHeight
	});

	rect.custom = {};
	rect.custom.counter = counter;

	canvas.add(rect);
	counter++;
	rectLeft += 200;
}

function findNewPos(distX, distY, target, obj) {
	// See whether to focus on X or Y axis
	if(Math.abs(distX) > Math.abs(distY)) {
		if (distX > 0) {
			target.setLeft(obj.getLeft() - target.getWidth());
		} else {
			target.setLeft(obj.getLeft() + obj.getWidth());
		}
	} else {
		if (distY > 0) {
			target.setTop(obj.getTop() - target.getHeight());
		} else {
			target.setTop(obj.getTop() + obj.getHeight());
		}
	}
}

canvas.on('object:moving', function (options) {
	// Sets corner position coordinates based on current angle, width and height
	options.target.setCoords();

	// Don't allow objects off the canvas
	if(options.target.getLeft() < snap) {
		options.target.setLeft(0);
	}

	if(options.target.getTop() < snap) {
		options.target.setTop(0);
	}

	if((options.target.getWidth() + options.target.getLeft()) > (canvasWidth - snap)) {
		options.target.setLeft(canvasWidth - options.target.getWidth());
	}

	if((options.target.getHeight() + options.target.getTop()) > (canvasHeight - snap)) {
		options.target.setTop(canvasHeight - options.target.getHeight());
	}

	// Loop...