所以我有下面的捕捉网格功能。当对象具有0角度时它可以正常工作,但是一旦它成角度(仅对于左侧和顶侧),它不会正确地捕捉到网格。这是因为它现在考虑了left和top属性,而不仅仅是左边或顶边。
我正在考虑的解决方案是使用三角形数学(毕达哥拉斯)但不确定如何获得当前的左/顶属性,因为target.left
和target.top
保存当前缩放对象的数据。
var canvas = new fabric.Canvas('c', {
selection: false
});
var grid = 50;
// create grid
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
}))
}
// add objects
canvas.add(new fabric.Rect({
left: 100,
top: 100,
strokeWidth: 0,
width: 50,
height: 50,
fill: '#faa',
originX: 'left',
angle: 50,
originY: 'top',
centeredRotation: true
}));
canvas.add(new fabric.Circle({
left: 300,
top: 300,
radius: 50,
fill: '#9f9',
originX: 'left',
originY: 'top',
strokeWidth: 0,
centeredRotation: true
}));
// snap to grid
canvas.on('object:moving', options => {
options.target.set({
left: Math.round(options.target.left / grid) * grid,
top: Math.round(options.target.top / grid) * grid
});
});
canvas.on('object:scaling', options => {
var target = options.target;
let grid = 50;
var 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, // add a multiplier to change closeness e.g. * 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.height;
attrs.scaleX = (attrs.scaleY / target.scaleY) * target.scaleX;
attrs.left += (w - target.width * attrs.scaleX);
attrs.top = snap.top;
}
break;
case 'mt':
if (dist.top < threshold) {
console.log("scaling");
attrs.scaleY = (h - (snap.top - target.top)) / target.height;
attrs.top = snap.top;
}
break;
case 'tr':
if (dist.right < dist.top && dist.right < threshold) {
attrs.scaleX = (snap.right - target.left) / target.width;
attrs.scaleY = (attrs.scaleX / target.scaleX) * target.scaleY;
attrs.top = target.top + (h - target.height * attrs.scaleY);
} else if (dist.top < threshold) {
attrs.scaleY = (h - (snap.top - target.top)) / target.height;
attrs.scaleX = (attrs.scaleY / target.scaleY) * target.scaleX;
attrs.top = snap.top;
}
break;
case 'ml':
if (dist.left < threshold) {
attrs.scaleX = (w - (snap.left - target.left)) / target.width;
attrs.left = snap.left;
}
break;
case 'mr':
if (dist.right < threshold) attrs.scaleX = (snap.right - target.left) / target.width;
break;
case 'bl':
if (dist.left < dist.bottom && dist.left < threshold) {
attrs.scaleX = (w - (snap.left - target.left)) / target.width;
attrs.scaleY = (attrs.scaleX / target.scaleX) * target.scaleY;
attrs.left = snap.left;
} else if (dist.bottom < threshold) {
attrs.scaleY = (snap.bottom - target.top) / target.height;
attrs.scaleX = (attrs.scaleY / target.scaleY) * target.scaleX;
attrs.left += (w - target.width * attrs.scaleX);
}
break;
case 'mb':
if (dist.bottom < threshold) attrs.scaleY = (snap.bottom - target.top) / target.height;
break;
case 'br':
if (dist.right < dist.bottom && dist.right < threshold) {
attrs.scaleX = (snap.right - target.left) / target.width;
attrs.scaleY = (attrs.scaleX / target.scaleX) * target.scaleY;
} else if (dist.bottom < threshold) {
attrs.scaleY = (snap.bottom - target.top) / target.height;
attrs.scaleX = (attrs.scaleY / target.scaleY) * target.scaleX;
}
break;
default:
break;
}
target.set(attrs);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.min.js"></script>
<canvas id="c" width="600" height="600"></canvas>