html5-canvas – Fabric.js画布上的多个裁剪区域

前端之家收集整理的这篇文章主要介绍了html5-canvas – Fabric.js画布上的多个裁剪区域前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
对于制作 Photo Collage Maker,我使用具有基于对象的裁剪功能的面料js.该功能非常好,但是裁剪区域内的图像无法缩放,移动或旋转.我想要固定位置裁剪区域,图像可以根据用户想要定位在固定裁剪区域内.

我google了,找到非常接近的解决方

var canvas = new fabric.Canvas('c');
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.rect(10,10,150,150);
ctx.rect(180,200,200);
ctx.closePath();
ctx.stroke();
ctx.clip();

Multiple Clipping Areas on fabric js canvas

其中一个裁剪区域的图像出现在另一裁剪区域中.如何避免这种情况,或者有另一种使用fabric js来完成这种方式的方法.

解决方法

这可以通过使用clipTo属性的Fabric来实现,但是必须在clipTo函数中反转转换(缩放和旋转).

当您在Fabric中使用clipTo属性时,缩放和旋转将在剪辑后应用,这意味着剪切与图像进行缩放和旋转.您必须通过在clipTo属性函数中应用转换的准确相反来对抗.

我的解决方案涉及到一个Fabric.Rect作为剪辑区域的“占位符”(这具有优点,因为您可以使用Fabric来移动对象,从而将剪辑区域移动.

请注意,我的解决方案使用Lo-Dash实用程序库,特别是_.bind()(参见上下文的代码).

Example Fiddle

分解

1.初始化面料

首先我们想要我们的画布,当然是:

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对象一个名称属性clipFor,所以clipTo函数可以找到他们想要剪切的对象:

clipRect1.set({
    clipFor: 'pug'
});
canvas.add(clipRect1);

不必是剪辑区域的实际对象,但它可以更轻松地进行管理,因为您可以使用Fabric移动它.

剪切功能

我们定义要由图像的clipTo属性单独使用的功能,以避免代码重复:

由于Image对象的angle属性以度为单位存储,我们将使用此属性将其转换为弧度.

function degToRad(degrees) {
    return degrees * (Math.PI / 180);
}

findByClipName()是一个方便的函数,它正在使用Lo-Dash,找到要剪切的Image对象的clipFor属性(例如,在下面的图片中,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();
}

注意:在上面的功能中,请参见下面的使用说明.

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 = 'http://fabricjs.com/lib/pug.jpg';

_.bind()做什么?

请注意,引用包装在_.bind()函数中.

我使用_.bind()有两个原因:

>我们需要将参考图像对象传递给clipByName()
> clipTo属性传递画布上下文,而不是对象.

基本上,_.bind()允许您创建一个使用您指定的对象作为此上下文的函数的版本.

来源

> http://lodash.com/docs#bind
> http://fabricjs.com/docs/fabric.Object.html#clipTo
> http://html5.litten.com/understanding-save-and-restore-for-the-canvas-context/

猜你在找的HTML5相关文章