应用clipTo在fabric.js图像路径不正确重新定位图像

问题描述:

请看看这个小提琴:应用clipTo在fabric.js图像路径不正确重新定位图像

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,那么图像加载完整的画布宽度没有问题(当然它也是完整的高度,这是我们不想要的)。

我不知道这里发生了什么,或者为什么这是发生所以任何帮助表示赞赏。

确保在画布和图像上有originXoriginY左边的topleft。另外 - 你并不需要将任何东西夹在画布上。我发现clipTo的唯一真正用途是将拼贴图像剪裁成其边界形状。如果你想限制从400像素以上被拖动的图像,我会建议呈现在其下方的矩形(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); 
}; 
+0

临屋但我不认为你完全理解了用例。这是一个HEADER映像(请参阅http://staging.wecora.com/boards/_Mwn5zsfpo1XB7RQpyPa)。我希望标题图像是画布宽度,但只有顶部300像素是可见的。我试图在画布和图像上的offsetX/Y没有效果。另外,你的其他解决方案似乎是这样的矫枉过正。这看起来像一个fabricjs错误,但不知道如何解决。 – JoshL

+0

@JoshL从这个网站,它看起来不像你需要使用画布。 – Brian

+0

使用HTML画布创建页面的缩略图图像,这就是为什么我们需要此功能。 – JoshL