在fabric.js中的图像上应用clipTo路径错误地重新定位图像

时间:2015-09-04 14:46:03

标签: fabricjs clipping

请看一下这个小提琴:

http://jsfiddle.net/2ktvyk4e/5/

    var imgUrl, snapshotCanvas;

    imgUrl = 'http://cdn-development.wecora.com/boards/backgrounds/000/001/388/cover/ocean-background.jpg';

    snapshotCanvas = new fabric.StaticCanvas('snapshotCanvas', {
      backgroundColor: '#e0e0e0',
      width: 1000,
      height: 1500
    });

    fabric.Image.fromURL(imgUrl, function(img) {
      img.set({
        width: 1000,
        left: 0,
        top: 0,
        clipTo: function(ctx) {
          return ctx.rect(0, 0, 1000, 400);
        }
      });
      return snapshotCanvas.add(img).renderAll();
    }, {
      crossOrigin: 'Anonymous'
    });

这很简单。我正在加载一个图像,然后尝试剪切它,以便画布的整个宽度,但剪裁,所以只显示前400个像素。由于某种原因,clipTo导致图像移动并莫名其妙地调整大小:

enter image description here

正如您所看到的,当应用剪切路径时,图像会在画布上重新定位。如果我删除clipTo,那么图像加载完整的画布宽度没问题(当然它也是全高度,我们不想要)。

我不知道这里发生了什么,或者为什么会发生这种情况,所以感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

确保您在画布和图片上留下originXoriginYtopleft。另外 - 你真的不需要在画布上剪辑任何东西。我发现clipTo的唯一真正用途是将拼贴图像剪切到它们的边界形状。如果你想限制图像被拖动到​​400px以上,我建议在它下面渲染一个矩形(evented = falseselectable = false),然后剪裁到那个矩形。

我把它放在一起没有clipTo(并改变了一些数字,所以我没有横向滚动)。它将图像渲染到画布的一半。

http://jsfiddle.net/2ktvyk4e/6/

编辑:

我挖掘了一些源代码,找到了clipByName方法和两个帮助方法来查找东西。我使用它来跟踪拼贴图像及其边界矩形(“图像”和“剪辑”)。我将它们存储在一个对象中:

imageObjects: { 
    'collage_0': http://some.tld/to/image.ext,
    'collage_1': http://some.tld/to/image2.ext 
}

用于查找剪辑或图像的辅助方法:

findClipByClipName: function (clipName) {
    var clip = _(canvas.getObjects()).where({ clipFor: clipName }).first();

    return clip;
},

findImageByClipFor: function (clipFor) {
    var image = _(canvas.getObjects()).where({ clipName: clipFor }).first();

    return image;
}, 

实际裁剪方法:

clipByName: function (ctx) {
    this.setCoords();
    var clipRect, scaleXTo1, scaleYTo1;
    clipRect = collage.findClipByClipName(this.clipName);
    scaleXTo1 = (1 / this.scaleX);
    scaleYTo1 = (1 / this.scaleY);
    ctx.save();

    var ctxLeft, ctxTop;
    ctxLeft = -(this.width / 2) + clipRect.strokeWidth;
    ctxTop = -(this.height / 2) + clipRect.strokeWidth;

    ctx.translate(ctxLeft, ctxTop);

    ctx.rotate(degToRad(this.angle * -1));
    ctx.scale(scaleXTo1, scaleYTo1);
    ctx.beginPath();
    ctx.rect(
        clipRect.left - this.oCoords.tl.x,
        clipRect.top - this.oCoords.tl.y,
        clipRect.width,
        clipRect.height
    );
    ctx.closePath();
    ctx.restore();

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

最后将图像添加到画布中,所有这些都汇集在一起​​:

var clipName, clip, image;

clipName = helpers.findKeyByValue(url, this.imageObjects);
clip = this.findClipByClipName(clipName);

image = new Image();
image.onload = function () {
    var collageImage = new fabric.Image(image, $.extend({}, collage.commonImageProps, {
        left: clip.left,
        top: clip.top,
        clipName: clipName,
        clipTo: function (ctx) {
            return _.bind(collage.clipByName, collageImage)(ctx);
        }
    }));

    collage.scaleImagesToClip(collageImage);
    canvas.add(collageImage);
};