这可以通过使用该clipTo
属性的 Fabric 来完成,但您必须在函数中“反转”转换(缩放和旋转)clipTo
。
在Fabric中使用该clipTo
属性时,缩放和旋转是在裁剪之后应用的,也就是说裁剪是随图像一起缩放和旋转的。您必须通过在属性函数中应用完全相反的转换来解决这个问题。clipTo
我的解决方案包括将一个Fabric.Rect
用作剪辑区域的“占位符”(这具有优势,因为您可以使用 Fabric 来移动对象,从而移动剪辑区域。
请注意,我的解决方案使用Lo-Dash实用程序库,特别是_.bind()
(参见上下文代码)。
分解
1.初始化Fabric
首先,我们当然需要画布:
var canvas = new fabric.Canvas('c');
2. 剪辑区域
var clipRect1 = new fabric.Rect({
originX: 'left',
originY: 'top',
left: 180,
top: 10,
width: 200,
height: 200,
fill: 'none',
stroke: 'black',
strokeWidth: 2,
selectable: false
});
我们给这些Rect
对象一个 name 属性,clipFor
所以clipTo
函数可以找到它们想要被剪裁的对象:
clipRect1.set({
clipFor: 'pug'
});
canvas.add(clipRect1);
剪辑区域不一定要有实际对象,但它更易于管理,因为您可以使用 Fabric 移动它。
3.剪辑功能
我们分别定义图像clipTo
属性使用的函数以避免代码重复:
由于angle
Image 对象的属性以度为单位存储,因此我们将使用它来将其转换为弧度。
function degToRad(degrees) {
return degrees * (Math.PI / 180);
}
findByClipName()
是一个方便的函数,它使用Lo-Dash来查找clipFor
要裁剪的 Image 对象的属性(例如,在下图中,name
将是'pug'
):
function findByClipName(name) {
return _(canvas.getObjects()).where({
clipFor: name
}).first()
}
这是完成工作的部分:
var clipByName = function (ctx) {
var clipRect = findByClipName(this.clipName);
var scaleXTo1 = (1 / this.scaleX);
var scaleYTo1 = (1 / this.scaleY);
ctx.save();
ctx.translate(0,0);
ctx.rotate(degToRad(this.angle * -1));
ctx.scale(scaleXTo1, scaleYTo1);
ctx.beginPath();
ctx.rect(
clipRect.left - this.left,
clipRect.top - this.top,
clipRect.width,
clipRect.height
);
ctx.closePath();
ctx.restore();
}
注意:有关上述函数中使用的说明,请参见下文。this
4.fabric.Image
对象使用clipByName()
最后,图像可以被实例化并使用如下clipByName
函数:
var pugImg = new Image();
pugImg.onload = function (img) {
var pug = new fabric.Image(pugImg, {
angle: 45,
width: 500,
height: 500,
left: 230,
top: 170,
scaleX: 0.3,
scaleY: 0.3,
clipName: 'pug',
clipTo: function(ctx) {
return _.bind(clipByName, pug)(ctx)
}
});
canvas.add(pug);
};
pugImg.src = 'https://fabricjs.com/lib/pug.jpg';
做什么_.bind()
?
请注意,引用包含在_.bind()
函数中。
我使用_.bind()
以下两个原因:
- 我们需要将引用
Image
对象传递给clipByName()
- 该
clipTo
属性被传递给画布上下文,而不是对象。
基本上,_.bind()
允许您创建一个使用您指定的对象作为this
上下文的函数版本。
来源
- https://lodash.com/docs#bind
- https://fabricjs.com/docs/fabric.Object.html#clipTo
- https://html5.litten.com/understanding-save-and-restore-for-the-canvas-context/